Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
f796e624
Unverified
提交
f796e624
authored
6月 12, 2018
作者:
Andrei Tokar
提交者:
GitHub
6月 12, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1188 from h2database/undo-log-split
Undo log split to reduce contention
上级
4737951c
e74aac10
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
15 个修改的文件
包含
531 行增加
和
415 行删除
+531
-415
AlterTableAddConstraint.java
h2/src/main/org/h2/command/ddl/AlterTableAddConstraint.java
+6
-2
CreateTable.java
h2/src/main/org/h2/command/ddl/CreateTable.java
+8
-4
Database.java
h2/src/main/org/h2/engine/Database.java
+3
-3
Trace.java
h2/src/main/org/h2/message/Trace.java
+4
-4
FileStore.java
h2/src/main/org/h2/mvstore/FileStore.java
+9
-11
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+289
-219
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+1
-1
RollbackDecisionMaker.java
h2/src/main/org/h2/mvstore/tx/RollbackDecisionMaker.java
+16
-13
Transaction.java
h2/src/main/org/h2/mvstore/tx/Transaction.java
+21
-25
TransactionMap.java
h2/src/main/org/h2/mvstore/tx/TransactionMap.java
+40
-25
TransactionStore.java
h2/src/main/org/h2/mvstore/tx/TransactionStore.java
+109
-97
StringUtils.java
h2/src/main/org/h2/util/StringUtils.java
+6
-2
TestConcurrent.java
h2/src/test/org/h2/test/store/TestConcurrent.java
+4
-2
TestStreamStore.java
h2/src/test/org/h2/test/store/TestStreamStore.java
+1
-1
TestTransactionStore.java
h2/src/test/org/h2/test/store/TestTransactionStore.java
+14
-6
没有找到文件。
h2/src/main/org/h2/command/ddl/AlterTableAddConstraint.java
浏览文件 @
f796e624
...
...
@@ -77,8 +77,12 @@ public class AlterTableAddConstraint extends SchemaCommand {
try
{
return
tryUpdate
();
}
catch
(
DbException
e
)
{
for
(
Index
index
:
createdIndexes
)
{
session
.
getDatabase
().
removeSchemaObject
(
session
,
index
);
try
{
for
(
Index
index
:
createdIndexes
)
{
session
.
getDatabase
().
removeSchemaObject
(
session
,
index
);
}
}
catch
(
Throwable
ex
)
{
e
.
addSuppressed
(
ex
);
}
throw
e
;
}
finally
{
...
...
h2/src/main/org/h2/command/ddl/CreateTable.java
浏览文件 @
f796e624
...
...
@@ -159,10 +159,14 @@ public class CreateTable extends CommandWithColumns {
}
}
}
catch
(
DbException
e
)
{
db
.
checkPowerOff
();
db
.
removeSchemaObject
(
session
,
table
);
if
(!
transactional
)
{
session
.
commit
(
true
);
try
{
db
.
checkPowerOff
();
db
.
removeSchemaObject
(
session
,
table
);
if
(!
transactional
)
{
session
.
commit
(
true
);
}
}
catch
(
Throwable
ex
)
{
e
.
addSuppressed
(
ex
);
}
throw
e
;
}
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
f796e624
...
...
@@ -752,6 +752,9 @@ public class Database implements DataHandler {
getPageStore
();
}
}
if
(
mvStore
!=
null
)
{
mvStore
.
getTransactionStore
().
init
();
}
systemUser
=
new
User
(
this
,
0
,
SYSTEM_USER_NAME
,
true
);
mainSchema
=
new
Schema
(
this
,
0
,
Constants
.
SCHEMA_MAIN
,
systemUser
,
true
);
infoSchema
=
new
Schema
(
this
,
-
1
,
"INFORMATION_SCHEMA"
,
systemUser
,
true
);
...
...
@@ -762,9 +765,6 @@ public class Database implements DataHandler {
systemUser
.
setAdmin
(
true
);
systemSession
=
new
Session
(
this
,
systemUser
,
++
nextSessionId
);
lobSession
=
new
Session
(
this
,
systemUser
,
++
nextSessionId
);
if
(
mvStore
!=
null
)
{
mvStore
.
getTransactionStore
().
init
(
systemSession
);
}
CreateTableData
data
=
new
CreateTableData
();
ArrayList
<
Column
>
cols
=
data
.
columns
;
Column
columnId
=
new
Column
(
"ID"
,
Value
.
INT
);
...
...
h2/src/main/org/h2/message/Trace.java
浏览文件 @
f796e624
...
...
@@ -300,10 +300,10 @@ public class Trace {
if
(!
space
)
{
buff
.
append
(
' '
);
}
buff
.
append
(
"*/"
)
.
append
(
StringUtils
.
javaEncode
(
sql
)).
append
(
StringUtils
.
javaEncode
(
params
)).
append
(
';'
);
buff
.
append
(
"*/"
)
;
StringUtils
.
javaEncode
(
sql
,
buff
);
StringUtils
.
javaEncode
(
params
,
buff
);
buff
.
append
(
';'
);
sql
=
buff
.
toString
();
traceWriter
.
write
(
TraceSystem
.
INFO
,
module
,
sql
,
null
);
}
...
...
h2/src/main/org/h2/mvstore/FileStore.java
浏览文件 @
f796e624
...
...
@@ -128,17 +128,15 @@ public class FileStore {
if
(
file
!=
null
)
{
return
;
}
if
(
fileName
!=
null
)
{
// ensure the Cache file system is registered
FilePathCache
.
INSTANCE
.
getScheme
();
FilePath
p
=
FilePath
.
get
(
fileName
);
// if no explicit scheme was specified, NIO is used
if
(
p
instanceof
FilePathDisk
&&
!
fileName
.
startsWith
(
p
.
getScheme
()
+
":"
))
{
// ensure the NIO file system is registered
FilePathNio
.
class
.
getName
();
fileName
=
"nio:"
+
fileName
;
}
// ensure the Cache file system is registered
FilePathCache
.
INSTANCE
.
getScheme
();
FilePath
p
=
FilePath
.
get
(
fileName
);
// if no explicit scheme was specified, NIO is used
if
(
p
instanceof
FilePathDisk
&&
!
fileName
.
startsWith
(
p
.
getScheme
()
+
":"
))
{
// ensure the NIO file system is registered
FilePathNio
.
class
.
getName
();
fileName
=
"nio:"
+
fileName
;
}
this
.
fileName
=
fileName
;
FilePath
f
=
FilePath
.
get
(
fileName
);
...
...
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
f796e624
差异被折叠。
点击展开。
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
f796e624
...
...
@@ -253,7 +253,7 @@ public class MVTableEngine implements TableEngine {
public
void
initTransactions
()
{
List
<
Transaction
>
list
=
transactionStore
.
getOpenTransactions
();
for
(
Transaction
t
:
list
)
{
if
(
t
.
getStatus
()
==
Transaction
.
STATUS_COMMITT
ING
)
{
if
(
t
.
getStatus
()
==
Transaction
.
STATUS_COMMITT
ED
)
{
t
.
commit
();
}
else
if
(
t
.
getStatus
()
!=
Transaction
.
STATUS_PREPARED
)
{
t
.
rollback
();
...
...
h2/src/main/org/h2/mvstore/tx/RollbackDecisionMaker.java
浏览文件 @
f796e624
...
...
@@ -30,19 +30,22 @@ final class RollbackDecisionMaker extends MVMap.DecisionMaker<Object[]> {
@Override
public
MVMap
.
Decision
decide
(
Object
[]
existingValue
,
Object
[]
providedValue
)
{
assert
decision
==
null
;
assert
existingValue
!=
null
;
VersionedValue
valueToRestore
=
(
VersionedValue
)
existingValue
[
2
];
long
operationId
;
if
(
valueToRestore
==
null
||
(
operationId
=
valueToRestore
.
getOperationId
())
==
0
||
TransactionStore
.
getTransactionId
(
operationId
)
==
transactionId
&&
TransactionStore
.
getLogId
(
operationId
)
<
toLogId
)
{
int
mapId
=
(
Integer
)
existingValue
[
0
];
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapId
);
if
(
map
!=
null
&&
!
map
.
isClosed
())
{
Object
key
=
existingValue
[
1
];
VersionedValue
previousValue
=
map
.
operate
(
key
,
valueToRestore
,
MVMap
.
DecisionMaker
.
DEFAULT
);
listener
.
onRollback
(
map
,
key
,
previousValue
,
valueToRestore
);
// normaly existingValue will always be there except of db initialization
// where some undo log enty was captured on disk but actual map entry was not
if
(
existingValue
!=
null
)
{
VersionedValue
valueToRestore
=
(
VersionedValue
)
existingValue
[
2
];
long
operationId
;
if
(
valueToRestore
==
null
||
(
operationId
=
valueToRestore
.
getOperationId
())
==
0
||
TransactionStore
.
getTransactionId
(
operationId
)
==
transactionId
&&
TransactionStore
.
getLogId
(
operationId
)
<
toLogId
)
{
int
mapId
=
(
Integer
)
existingValue
[
0
];
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapId
);
if
(
map
!=
null
&&
!
map
.
isClosed
())
{
Object
key
=
existingValue
[
1
];
VersionedValue
previousValue
=
map
.
operate
(
key
,
valueToRestore
,
MVMap
.
DecisionMaker
.
DEFAULT
);
listener
.
onRollback
(
map
,
key
,
previousValue
,
valueToRestore
);
}
}
}
decision
=
MVMap
.
Decision
.
REMOVE
;
...
...
h2/src/main/org/h2/mvstore/tx/Transaction.java
浏览文件 @
f796e624
...
...
@@ -32,41 +32,36 @@ public class Transaction {
*/
public
static
final
int
STATUS_PREPARED
=
2
;
/**
* The status of a transaction that is being committed, but possibly not
* yet finished. A transactions can go into this state when the store is
* closed while the transaction is committing. When opening a store,
* such transactions should be committed.
*/
public
static
final
int
STATUS_COMMITTING
=
3
;
/**
* The status of a transaction that has been logically committed or rather
* marked as committed, because it might be still listed among prepared,
* if it was prepared for commit
, u
ndo log entries might still exists for it
* if it was prepared for commit
. U
ndo log entries might still exists for it
* and not all of it's changes within map's are re-written as committed yet.
* Nevertheless, those changes should be already viewed by other
* transactions as committed.
* This transaction's id can not be re-used until all the above is completed
* This transaction's id can not be re-used until all
of
the above is completed
* and transaction is closed.
* A transactions can be observed in this state when the store was
* closed while the transaction was not closed yet.
* When opening a store, such transactions will automatically
* be processed and closed as committed.
*/
p
rivate
static
final
int
STATUS_COMMITTED
=
4
;
p
ublic
static
final
int
STATUS_COMMITTED
=
3
;
/**
* The status of a transaction that currently in a process of rolling back
* to a savepoint.
*/
private
static
final
int
STATUS_ROLLING_BACK
=
5
;
private
static
final
int
STATUS_ROLLING_BACK
=
4
;
/**
* The status of a transaction that has been rolled back completely,
* but undo operations are not finished yet.
*/
private
static
final
int
STATUS_ROLLED_BACK
=
6
;
private
static
final
int
STATUS_ROLLED_BACK
=
5
;
private
static
final
String
STATUS_NAMES
[]
=
{
"CLOSED"
,
"OPEN"
,
"PREPARED"
,
"COMMITTING"
,
"COMMITTED"
,
"ROLLING_BACK"
,
"ROLLED_BACK"
"CLOSED"
,
"OPEN"
,
"PREPARED"
,
"COMMITTED"
,
"ROLLING_BACK"
,
"ROLLED_BACK"
};
static
final
int
LOG_ID_BITS
=
40
;
private
static
final
int
LOG_ID_BITS1
=
LOG_ID_BITS
+
1
;
...
...
@@ -175,6 +170,11 @@ public class Transaction {
return
getStatus
(
statusAndLogId
.
get
());
}
/**
* Changes transaction status to a specified value
* @param status to be set
* @return transaction state as it was before status change
*/
long
setStatus
(
int
status
)
{
while
(
true
)
{
long
currentState
=
statusAndLogId
.
get
();
...
...
@@ -192,23 +192,19 @@ public class Transaction {
case
STATUS_PREPARED:
valid
=
currentStatus
==
STATUS_OPEN
;
break
;
case
STATUS_COMMITT
ING
:
case
STATUS_COMMITT
ED
:
valid
=
currentStatus
==
STATUS_OPEN
||
currentStatus
==
STATUS_PREPARED
||
// this case is only possible if called
// from endLeftoverTransactions()
currentStatus
==
STATUS_COMMITTING
;
break
;
case
STATUS_COMMITTED:
valid
=
currentStatus
==
STATUS_COMMITTING
;
currentStatus
==
STATUS_COMMITTED
;
break
;
case
STATUS_ROLLED_BACK:
valid
=
currentStatus
==
STATUS_OPEN
||
currentStatus
==
STATUS_PREPARED
;
break
;
case
STATUS_CLOSED:
valid
=
currentStatus
==
STATUS_COMMITTING
||
currentStatus
==
STATUS_COMMITTED
||
valid
=
currentStatus
==
STATUS_COMMITTED
||
currentStatus
==
STATUS_ROLLED_BACK
;
break
;
default
:
...
...
@@ -365,11 +361,11 @@ public class Transaction {
Throwable
ex
=
null
;
boolean
hasChanges
=
false
;
try
{
long
state
=
setStatus
(
STATUS_COMMITT
ING
);
long
state
=
setStatus
(
STATUS_COMMITT
ED
);
hasChanges
=
hasChanges
(
state
);
int
previousStatus
=
getStatus
(
state
);
if
(
hasChanges
)
{
long
logId
=
getLogId
(
state
);
store
.
commit
(
this
,
logId
);
store
.
commit
(
this
,
previousStatus
==
STATUS_COMMITTED
);
}
}
catch
(
Throwable
e
)
{
ex
=
e
;
...
...
h2/src/main/org/h2/mvstore/tx/TransactionMap.java
浏览文件 @
f796e624
...
...
@@ -77,11 +77,22 @@ public class TransactionMap<K, V> {
// when none of the variables concurrently changes it's value.
BitSet
committingTransactions
;
MVMap
.
RootReference
mapRootReference
;
MVMap
.
RootReference
undoLogRootReference
;
MVMap
.
RootReference
[]
undoLogRootReferences
;
long
undoLogSize
;
do
{
committingTransactions
=
store
.
committingTransactions
.
get
();
mapRootReference
=
map
.
getRoot
();
undoLogRootReference
=
store
.
undoLog
.
getRoot
();
BitSet
opentransactions
=
store
.
openTransactions
.
get
();
undoLogRootReferences
=
new
MVMap
.
RootReference
[
opentransactions
.
length
()];
undoLogSize
=
0
;
for
(
int
i
=
opentransactions
.
nextSetBit
(
0
);
i
>=
0
;
i
=
opentransactions
.
nextSetBit
(
i
+
1
))
{
MVMap
<
Long
,
Object
[]>
undoLog
=
store
.
undoLogs
[
i
];
if
(
undoLog
!=
null
)
{
MVMap
.
RootReference
rootReference
=
undoLog
.
getRoot
();
undoLogRootReferences
[
i
]
=
rootReference
;
undoLogSize
+=
rootReference
.
root
.
getTotalCount
();
}
}
}
while
(
committingTransactions
!=
store
.
committingTransactions
.
get
()
||
mapRootReference
!=
map
.
getRoot
());
// Now we have a snapshot, where mapRootReference points to state of the map,
...
...
@@ -89,8 +100,6 @@ public class TransactionMap<K, V> {
// and committingTransactions mask tells us which of seemingly uncommitted changes
// should be considered as committed.
// Subsequent processing uses this snapshot info only.
Page
undoRootPage
=
undoLogRootReference
.
root
;
long
undoLogSize
=
undoRootPage
.
getTotalCount
();
Page
mapRootPage
=
mapRootReference
.
root
;
long
size
=
mapRootPage
.
getTotalCount
();
// if we are looking at the map without any uncommitted values
...
...
@@ -112,7 +121,8 @@ public class TransactionMap<K, V> {
long
operationId
=
currentValue
.
getOperationId
();
if
(
operationId
!=
0
)
{
// skip committed entries
int
txId
=
TransactionStore
.
getTransactionId
(
operationId
);
boolean
isVisible
=
txId
==
transaction
.
transactionId
||
committingTransactions
.
get
(
txId
);
boolean
isVisible
=
txId
==
transaction
.
transactionId
||
committingTransactions
.
get
(
txId
);
Object
v
=
isVisible
?
currentValue
.
value
:
currentValue
.
getCommittedValue
();
if
(
v
==
null
)
{
--
size
;
...
...
@@ -120,26 +130,31 @@ public class TransactionMap<K, V> {
}
}
}
else
{
// The undo log is much smaller than the map - scan the undo log, and then lookup relevant map entry.
Cursor
<
Long
,
Object
[]>
cursor
=
new
Cursor
<>(
undoRootPage
,
null
);
while
(
cursor
.
hasNext
())
{
cursor
.
next
();
Object
op
[]
=
cursor
.
getValue
();
if
((
int
)
op
[
0
]
==
map
.
getId
())
{
VersionedValue
currentValue
=
map
.
get
(
mapRootPage
,
op
[
1
]);
// If map entry is not there, then we never counted it, in the first place, so skip it.
// This is possible when undo entry exists because it belongs
// to a committed but not yet closed transaction,
// and it was later deleted by some other already committed and closed transaction.
if
(
currentValue
!=
null
)
{
// only the last undo entry for any given map key should be considered
long
operationId
=
cursor
.
getKey
();
if
(
currentValue
.
getOperationId
()
==
operationId
)
{
int
txId
=
TransactionStore
.
getTransactionId
(
operationId
);
boolean
isVisible
=
txId
==
transaction
.
transactionId
||
committingTransactions
.
get
(
txId
);
Object
v
=
isVisible
?
currentValue
.
value
:
currentValue
.
getCommittedValue
();
if
(
v
==
null
)
{
--
size
;
// The undo logs are much smaller than the map - scan all undo logs, and then lookup relevant map entry.
for
(
MVMap
.
RootReference
undoLogRootReference
:
undoLogRootReferences
)
{
if
(
undoLogRootReference
!=
null
)
{
Cursor
<
Long
,
Object
[]>
cursor
=
new
Cursor
<>(
undoLogRootReference
.
root
,
null
);
while
(
cursor
.
hasNext
())
{
cursor
.
next
();
Object
op
[]
=
cursor
.
getValue
();
if
((
int
)
op
[
0
]
==
map
.
getId
())
{
VersionedValue
currentValue
=
map
.
get
(
mapRootPage
,
op
[
1
]);
// If map entry is not there, then we never counted it, in the first place, so skip it.
// This is possible when undo entry exists because it belongs
// to a committed but not yet closed transaction,
// and it was later deleted by some other already committed and closed transaction.
if
(
currentValue
!=
null
)
{
// only the last undo entry for any given map key should be considered
long
operationId
=
cursor
.
getKey
();
if
(
currentValue
.
getOperationId
()
==
operationId
)
{
int
txId
=
TransactionStore
.
getTransactionId
(
operationId
);
boolean
isVisible
=
txId
==
transaction
.
transactionId
||
committingTransactions
.
get
(
txId
);
Object
v
=
isVisible
?
currentValue
.
value
:
currentValue
.
getCommittedValue
();
if
(
v
==
null
)
{
--
size
;
}
}
}
}
}
...
...
h2/src/main/org/h2/mvstore/tx/TransactionStore.java
浏览文件 @
f796e624
差异被折叠。
点击展开。
h2/src/main/org/h2/util/StringUtils.java
浏览文件 @
f796e624
...
...
@@ -148,8 +148,13 @@ public class StringUtils {
* @return the Java representation
*/
public
static
String
javaEncode
(
String
s
)
{
StringBuilder
buff
=
new
StringBuilder
(
s
.
length
());
javaEncode
(
s
,
buff
);
return
buff
.
toString
();
}
public
static
void
javaEncode
(
String
s
,
StringBuilder
buff
)
{
int
length
=
s
.
length
();
StringBuilder
buff
=
new
StringBuilder
(
length
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
char
c
=
s
.
charAt
(
i
);
switch
(
c
)
{
...
...
@@ -202,7 +207,6 @@ public class StringUtils {
}
}
}
return
buff
.
toString
();
}
/**
...
...
h2/src/test/org/h2/test/store/TestConcurrent.java
浏览文件 @
f796e624
...
...
@@ -513,8 +513,10 @@ public class TestConcurrent extends TestMVStore {
Thread
.
sleep
(
1
);
}
Exception
e
=
task
.
getException
();
assertEquals
(
DataUtils
.
ERROR_CLOSED
,
DataUtils
.
getErrorCode
(
e
.
getMessage
()));
if
(
e
!=
null
)
{
assertEquals
(
DataUtils
.
ERROR_CLOSED
,
DataUtils
.
getErrorCode
(
e
.
getMessage
()));
}
}
catch
(
IllegalStateException
e
)
{
// sometimes storing works, in which case
// closing must fail
...
...
h2/src/test/org/h2/test/store/TestStreamStore.java
浏览文件 @
f796e624
...
...
@@ -151,7 +151,7 @@ public class TestStreamStore extends TestBase {
long
readCount
=
s
.
getFileStore
().
getReadCount
();
// the read count should be low because new blocks
// are appended at the end (not between existing blocks)
assertTrue
(
"rc: "
+
readCount
,
readCount
<=
17
);
assertTrue
(
"rc: "
+
readCount
,
readCount
<=
20
);
map
=
s
.
openMap
(
"data"
);
assertTrue
(
"size: "
+
map
.
size
(),
map
.
sizeAsLong
()
>=
200
);
s
.
close
();
...
...
h2/src/test/org/h2/test/store/TestTransactionStore.java
浏览文件 @
f796e624
...
...
@@ -204,6 +204,7 @@ public class TestTransactionStore extends TestBase {
break
;
}
}
task
.
get
();
// we expect at least 10% the operations were successful
assertTrue
(
failCount
.
toString
()
+
" >= "
+
(
count
*
0.9
),
failCount
.
get
()
<
count
*
0.9
);
...
...
@@ -395,24 +396,22 @@ public class TestTransactionStore extends TestBase {
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
)
{
if
(
hasDataUndoLog
(
s
))
{
break
;
}
}
// re-open
the store, because we have opened
//
the undoLog map with the wrong data typ
e
// re-open
TransactionStore, because we rolled back
//
underlying MVStore without rolling back TranactionStor
e
s
.
close
();
s
=
MVStore
.
open
(
fileName
);
ts
=
new
TransactionStore
(
s
);
List
<
Transaction
>
list
=
ts
.
getOpenTransactions
();
if
(
list
.
size
()
!=
0
)
{
tx
=
list
.
get
(
0
);
if
(
tx
.
getStatus
()
==
Transaction
.
STATUS_COMMITT
ING
)
{
if
(
tx
.
getStatus
()
==
Transaction
.
STATUS_COMMITT
ED
)
{
i
++;
}
}
...
...
@@ -422,6 +421,15 @@ public class TestTransactionStore extends TestBase {
}
}
private
boolean
hasDataUndoLog
(
MVStore
s
)
{
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
if
(
s
.
hasData
(
TransactionStore
.
getUndoLogName
(
true
,
1
)))
{
return
true
;
}
}
return
false
;
}
private
void
testGetModifiedMaps
()
{
MVStore
s
=
MVStore
.
open
(
null
);
TransactionStore
ts
=
new
TransactionStore
(
s
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论