Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
422f2826
Unverified
提交
422f2826
authored
12月 27, 2018
作者:
Andrei Tokar
提交者:
GitHub
12月 27, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1627 from h2database/append-single
Use lock to protect append buffer
上级
c3afed94
770812c7
全部展开
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
389 行增加
和
263 行删除
+389
-263
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+297
-229
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+1
-1
Page.java
h2/src/main/org/h2/mvstore/Page.java
+30
-0
MVRTreeMap.java
h2/src/main/org/h2/mvstore/rtree/MVRTreeMap.java
+1
-1
Transaction.java
h2/src/main/org/h2/mvstore/tx/Transaction.java
+40
-18
TransactionMap.java
h2/src/main/org/h2/mvstore/tx/TransactionMap.java
+19
-13
TransactionStore.java
h2/src/main/org/h2/mvstore/tx/TransactionStore.java
+1
-1
没有找到文件。
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
422f2826
差异被折叠。
点击展开。
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
422f2826
...
@@ -1401,7 +1401,7 @@ public class MVStore implements AutoCloseable {
...
@@ -1401,7 +1401,7 @@ public class MVStore implements AutoCloseable {
try
{
try
{
ChunkIdsCollector
collector
=
new
ChunkIdsCollector
(
meta
.
getId
());
ChunkIdsCollector
collector
=
new
ChunkIdsCollector
(
meta
.
getId
());
long
oldestVersionToKeep
=
getOldestVersionToKeep
();
long
oldestVersionToKeep
=
getOldestVersionToKeep
();
MVMap
.
RootReference
rootReference
=
meta
.
g
etRoot
();
MVMap
.
RootReference
rootReference
=
meta
.
flushAndG
etRoot
();
if
(
fast
)
{
if
(
fast
)
{
MVMap
.
RootReference
previous
;
MVMap
.
RootReference
previous
;
while
(
rootReference
.
version
>=
oldestVersionToKeep
&&
(
previous
=
rootReference
.
previous
)
!=
null
)
{
while
(
rootReference
.
version
>=
oldestVersionToKeep
&&
(
previous
=
rootReference
.
previous
)
!=
null
)
{
...
...
h2/src/main/org/h2/mvstore/Page.java
浏览文件 @
422f2826
...
@@ -493,6 +493,16 @@ public abstract class Page implements Cloneable
...
@@ -493,6 +493,16 @@ public abstract class Page implements Cloneable
return
bKeys
;
return
bKeys
;
}
}
abstract
void
expand
(
int
extraKeyCount
,
Object
[]
extraKeys
,
Object
[]
extraValues
);
final
void
expandKeys
(
int
extraKeyCount
,
Object
[]
extraKeys
)
{
int
keyCount
=
getKeyCount
();
Object
[]
newKeys
=
createKeyStorage
(
keyCount
+
extraKeyCount
);
System
.
arraycopy
(
keys
,
0
,
newKeys
,
0
,
keyCount
);
System
.
arraycopy
(
extraKeys
,
0
,
newKeys
,
keyCount
,
extraKeyCount
);
keys
=
newKeys
;
}
/**
/**
* Get the total number of key-value pairs, including child pages.
* Get the total number of key-value pairs, including child pages.
*
*
...
@@ -1012,6 +1022,11 @@ public abstract class Page implements Cloneable
...
@@ -1012,6 +1022,11 @@ public abstract class Page implements Cloneable
return
newPage
;
return
newPage
;
}
}
@Override
public
void
expand
(
int
keyCount
,
Object
[]
extraKys
,
Object
[]
extraValues
)
{
throw
new
UnsupportedOperationException
();
}
@Override
@Override
public
long
getTotalCount
()
{
public
long
getTotalCount
()
{
assert
!
isComplete
()
||
totalCount
==
calculateTotalCount
()
:
assert
!
isComplete
()
||
totalCount
==
calculateTotalCount
()
:
...
@@ -1324,6 +1339,21 @@ public abstract class Page implements Cloneable
...
@@ -1324,6 +1339,21 @@ public abstract class Page implements Cloneable
return
newPage
;
return
newPage
;
}
}
@Override
public
void
expand
(
int
extraKeyCount
,
Object
[]
extraKeys
,
Object
[]
extraValues
)
{
int
keyCount
=
getKeyCount
();
expandKeys
(
extraKeyCount
,
extraKeys
);
if
(
values
!=
null
)
{
Object
[]
newValues
=
createValueStorage
(
keyCount
+
extraKeyCount
);
System
.
arraycopy
(
values
,
0
,
newValues
,
0
,
keyCount
);
System
.
arraycopy
(
extraValues
,
0
,
newValues
,
keyCount
,
extraKeyCount
);
values
=
newValues
;
}
if
(
isPersistent
())
{
recalculateMemory
();
}
}
@Override
@Override
public
long
getTotalCount
()
{
public
long
getTotalCount
()
{
return
getKeyCount
();
return
getKeyCount
();
...
...
h2/src/main/org/h2/mvstore/rtree/MVRTreeMap.java
浏览文件 @
422f2826
...
@@ -134,7 +134,7 @@ public final class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
...
@@ -134,7 +134,7 @@ public final class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
int
attempt
=
0
;
int
attempt
=
0
;
while
(
true
)
{
while
(
true
)
{
++
attempt
;
++
attempt
;
RootReference
rootReference
=
g
etRoot
();
RootReference
rootReference
=
flushAndG
etRoot
();
Page
p
=
rootReference
.
root
.
copy
(
true
);
Page
p
=
rootReference
.
root
.
copy
(
true
);
V
result
=
operate
(
p
,
key
,
value
,
decisionMaker
);
V
result
=
operate
(
p
,
key
,
value
,
decisionMaker
);
if
(!
p
.
isLeaf
()
&&
p
.
getTotalCount
()
==
0
)
{
if
(!
p
.
isLeaf
()
&&
p
.
getTotalCount
()
==
0
)
{
...
...
h2/src/main/org/h2/mvstore/tx/Transaction.java
浏览文件 @
422f2826
...
@@ -61,7 +61,7 @@ public class Transaction {
...
@@ -61,7 +61,7 @@ public class Transaction {
*/
*/
private
static
final
int
STATUS_ROLLED_BACK
=
5
;
private
static
final
int
STATUS_ROLLED_BACK
=
5
;
private
static
final
String
STATUS_NAMES
[]
=
{
private
static
final
String
[]
STATUS_NAMES
=
{
"CLOSED"
,
"OPEN"
,
"PREPARED"
,
"COMMITTED"
,
"ROLLING_BACK"
,
"ROLLED_BACK"
"CLOSED"
,
"OPEN"
,
"PREPARED"
,
"COMMITTED"
,
"ROLLING_BACK"
,
"ROLLED_BACK"
};
};
static
final
int
LOG_ID_BITS
=
40
;
static
final
int
LOG_ID_BITS
=
40
;
...
@@ -91,7 +91,7 @@ public class Transaction {
...
@@ -91,7 +91,7 @@ public class Transaction {
/**
/**
* This is really a transaction identity, because it's not re-used.
* This is really a transaction identity, because it's not re-used.
*/
*/
public
final
long
sequenceNum
;
final
long
sequenceNum
;
/*
/*
* Transaction state is an atomic composite field:
* Transaction state is an atomic composite field:
...
@@ -138,12 +138,17 @@ public class Transaction {
...
@@ -138,12 +138,17 @@ public class Transaction {
/**
/**
* Map on which this transaction is blocked.
* Map on which this transaction is blocked.
*/
*/
MVMap
<?,
VersionedValue
>
blockingMap
;
private
MVMap
<?,
VersionedValue
>
blockingMap
;
/**
/**
* Key in blockingMap on which this transaction is blocked.
* Key in blockingMap on which this transaction is blocked.
*/
*/
Object
blockingKey
;
private
Object
blockingKey
;
/**
* Whether other transaction(s) are waiting for this to close.
*/
private
volatile
boolean
notificationRequested
;
Transaction
(
TransactionStore
store
,
int
transactionId
,
long
sequenceNum
,
int
status
,
Transaction
(
TransactionStore
store
,
int
transactionId
,
long
sequenceNum
,
int
status
,
...
@@ -237,7 +242,8 @@ public class Transaction {
...
@@ -237,7 +242,8 @@ public class Transaction {
}
}
public
int
getBlockerId
()
{
public
int
getBlockerId
()
{
return
blockingTransaction
==
null
?
0
:
blockingTransaction
.
ownerId
;
Transaction
blocker
=
this
.
blockingTransaction
;
return
blocker
==
null
?
0
:
blocker
.
ownerId
;
}
}
/**
/**
...
@@ -390,21 +396,27 @@ public class Transaction {
...
@@ -390,21 +396,27 @@ public class Transaction {
public
void
rollbackToSavepoint
(
long
savepointId
)
{
public
void
rollbackToSavepoint
(
long
savepointId
)
{
long
lastState
=
setStatus
(
STATUS_ROLLING_BACK
);
long
lastState
=
setStatus
(
STATUS_ROLLING_BACK
);
long
logId
=
getLogId
(
lastState
);
long
logId
=
getLogId
(
lastState
);
boolean
success
;
try
{
try
{
store
.
rollbackTo
(
this
,
logId
,
savepointId
);
store
.
rollbackTo
(
this
,
logId
,
savepointId
);
}
finally
{
}
finally
{
if
(
notificationRequested
)
{
notifyAllWaitingTransactions
();
notifyAllWaitingTransactions
();
}
long
expectedState
=
composeState
(
STATUS_ROLLING_BACK
,
logId
,
hasRollback
(
lastState
));
long
expectedState
=
composeState
(
STATUS_ROLLING_BACK
,
logId
,
hasRollback
(
lastState
));
long
newState
=
composeState
(
STATUS_OPEN
,
savepointId
,
true
);
long
newState
=
composeState
(
STATUS_OPEN
,
savepointId
,
true
);
if
(!
statusAndLogId
.
compareAndSet
(
expectedState
,
newState
))
{
do
{
success
=
statusAndLogId
.
compareAndSet
(
expectedState
,
newState
);
}
while
(!
success
&&
statusAndLogId
.
get
()
==
expectedState
);
}
// this is moved outside of finally block to avert masking original exception, if any
if
(!
success
)
{
throw
DataUtils
.
newIllegalStateException
(
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TRANSACTION_ILLEGAL_STATE
,
DataUtils
.
ERROR_TRANSACTION_ILLEGAL_STATE
,
"Transaction {0} concurrently modified "
+
"Transaction {0} concurrently modified while rollback to savepoint was in progress"
,
"while rollback to savepoint was in progress"
,
transactionId
);
transactionId
);
}
}
}
}
}
/**
/**
* Roll the transaction back. Afterwards, this transaction is closed.
* Roll the transaction back. Afterwards, this transaction is closed.
...
@@ -474,7 +486,7 @@ public class Transaction {
...
@@ -474,7 +486,7 @@ public class Transaction {
void
closeIt
()
{
void
closeIt
()
{
long
lastState
=
setStatus
(
STATUS_CLOSED
);
long
lastState
=
setStatus
(
STATUS_CLOSED
);
store
.
store
.
deregisterVersionUsage
(
txCounter
);
store
.
store
.
deregisterVersionUsage
(
txCounter
);
if
(
hasChanges
(
lastState
)
||
hasRollback
(
lastState
)
)
{
if
(
(
hasChanges
(
lastState
)
||
hasRollback
(
lastState
))
&&
notificationRequested
)
{
notifyAllWaitingTransactions
();
notifyAllWaitingTransactions
();
}
}
}
}
...
@@ -483,7 +495,10 @@ public class Transaction {
...
@@ -483,7 +495,10 @@ public class Transaction {
notifyAll
();
notifyAll
();
}
}
public
boolean
waitFor
(
Transaction
toWaitFor
)
{
public
boolean
waitFor
(
Transaction
toWaitFor
,
MVMap
<?,
VersionedValue
>
map
,
Object
key
)
{
blockingTransaction
=
toWaitFor
;
blockingMap
=
map
;
blockingKey
=
key
;
if
(
isDeadlocked
(
toWaitFor
))
{
if
(
isDeadlocked
(
toWaitFor
))
{
StringBuilder
details
=
new
StringBuilder
(
StringBuilder
details
=
new
StringBuilder
(
String
.
format
(
"Transaction %d has been chosen as a deadlock victim. Details:%n"
,
transactionId
));
String
.
format
(
"Transaction %d has been chosen as a deadlock victim. Details:%n"
,
transactionId
));
...
@@ -504,7 +519,6 @@ public class Transaction {
...
@@ -504,7 +519,6 @@ public class Transaction {
}
}
}
}
blockingTransaction
=
toWaitFor
;
try
{
try
{
return
toWaitFor
.
waitForThisToEnd
(
timeoutMillis
);
return
toWaitFor
.
waitForThisToEnd
(
timeoutMillis
);
}
finally
{
}
finally
{
...
@@ -527,6 +541,7 @@ public class Transaction {
...
@@ -527,6 +541,7 @@ public class Transaction {
private
synchronized
boolean
waitForThisToEnd
(
int
millis
)
{
private
synchronized
boolean
waitForThisToEnd
(
int
millis
)
{
long
until
=
System
.
currentTimeMillis
()
+
millis
;
long
until
=
System
.
currentTimeMillis
()
+
millis
;
notificationRequested
=
true
;
long
state
;
long
state
;
int
status
;
int
status
;
while
((
status
=
getStatus
(
state
=
statusAndLogId
.
get
()))
!=
STATUS_CLOSED
while
((
status
=
getStatus
(
state
=
statusAndLogId
.
get
()))
!=
STATUS_CLOSED
...
@@ -557,8 +572,15 @@ public class Transaction {
...
@@ -557,8 +572,15 @@ public class Transaction {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
long
state
=
statusAndLogId
.
get
();
return
transactionId
+
"("
+
sequenceNum
+
") "
+
stateToString
();
return
transactionId
+
"("
+
sequenceNum
+
") "
+
STATUS_NAMES
[
getStatus
(
state
)]
+
" "
+
getLogId
(
state
);
}
private
String
stateToString
()
{
return
stateToString
(
statusAndLogId
.
get
());
}
private
static
String
stateToString
(
long
state
)
{
return
STATUS_NAMES
[
getStatus
(
state
)]
+
(
hasRollback
(
state
)
?
"<"
:
""
)
+
" "
+
getLogId
(
state
);
}
}
...
...
h2/src/main/org/h2/mvstore/tx/TransactionMap.java
浏览文件 @
422f2826
...
@@ -46,7 +46,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -46,7 +46,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
/**
/**
* The transaction which is used for this map.
* The transaction which is used for this map.
*/
*/
final
Transaction
transaction
;
private
final
Transaction
transaction
;
TransactionMap
(
Transaction
transaction
,
MVMap
<
K
,
VersionedValue
>
map
)
{
TransactionMap
(
Transaction
transaction
,
MVMap
<
K
,
VersionedValue
>
map
)
{
this
.
transaction
=
transaction
;
this
.
transaction
=
transaction
;
...
@@ -105,16 +105,16 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -105,16 +105,16 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
long
undoLogSize
;
long
undoLogSize
;
do
{
do
{
committingTransactions
=
store
.
committingTransactions
.
get
();
committingTransactions
=
store
.
committingTransactions
.
get
();
mapRootReference
=
map
.
g
etRoot
();
mapRootReference
=
map
.
flushAndG
etRoot
();
BitSet
opentransactions
=
store
.
openTransactions
.
get
();
BitSet
opentransactions
=
store
.
openTransactions
.
get
();
undoLogRootReferences
=
new
MVMap
.
RootReference
[
opentransactions
.
length
()];
undoLogRootReferences
=
new
MVMap
.
RootReference
[
opentransactions
.
length
()];
undoLogSize
=
0
;
undoLogSize
=
0
;
for
(
int
i
=
opentransactions
.
nextSetBit
(
0
);
i
>=
0
;
i
=
opentransactions
.
nextSetBit
(
i
+
1
))
{
for
(
int
i
=
opentransactions
.
nextSetBit
(
0
);
i
>=
0
;
i
=
opentransactions
.
nextSetBit
(
i
+
1
))
{
MVMap
<
Long
,
Object
[]>
undoLog
=
store
.
undoLogs
[
i
];
MVMap
<
Long
,
Object
[]>
undoLog
=
store
.
undoLogs
[
i
];
if
(
undoLog
!=
null
)
{
if
(
undoLog
!=
null
)
{
MVMap
.
RootReference
rootReference
=
undoLog
.
g
etRoot
();
MVMap
.
RootReference
rootReference
=
undoLog
.
flushAndG
etRoot
();
undoLogRootReferences
[
i
]
=
rootReference
;
undoLogRootReferences
[
i
]
=
rootReference
;
undoLogSize
+=
rootReference
.
root
.
getTotalCount
()
+
rootReference
.
getAppendCounter
();
undoLogSize
+=
rootReference
.
getTotalCount
();
}
}
}
}
}
while
(
committingTransactions
!=
store
.
committingTransactions
.
get
()
||
}
while
(
committingTransactions
!=
store
.
committingTransactions
.
get
()
||
...
@@ -125,7 +125,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -125,7 +125,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
// should be considered as committed.
// should be considered as committed.
// Subsequent processing uses this snapshot info only.
// Subsequent processing uses this snapshot info only.
Page
mapRootPage
=
mapRootReference
.
root
;
Page
mapRootPage
=
mapRootReference
.
root
;
long
size
=
mapRoot
Pag
e
.
getTotalCount
();
long
size
=
mapRoot
Referenc
e
.
getTotalCount
();
// if we are looking at the map without any uncommitted values
// if we are looking at the map without any uncommitted values
if
(
undoLogSize
==
0
)
{
if
(
undoLogSize
==
0
)
{
return
size
;
return
size
;
...
@@ -241,6 +241,16 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -241,6 +241,16 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
return
set
(
key
,
decisionMaker
);
return
set
(
key
,
decisionMaker
);
}
}
/**
* Appends entry to uderlying map. This method may be used concurrently,
* but latest appended values are not guaranteed to be visible.
* @param key should be higher in map's order than any existing key
* @param value to be appended
*/
public
void
append
(
K
key
,
V
value
)
{
map
.
append
(
key
,
VersionedValueUncommitted
.
getInstance
(
transaction
.
log
(
map
.
getId
(),
key
,
null
),
value
,
null
));
}
/**
/**
* Lock row for the given key.
* Lock row for the given key.
* <p>
* <p>
...
@@ -298,16 +308,12 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -298,16 +308,12 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
assert
decision
!=
MVMap
.
Decision
.
REPEAT
;
assert
decision
!=
MVMap
.
Decision
.
REPEAT
;
blockingTransaction
=
decisionMaker
.
getBlockingTransaction
();
blockingTransaction
=
decisionMaker
.
getBlockingTransaction
();
if
(
decision
!=
MVMap
.
Decision
.
ABORT
||
blockingTransaction
==
null
)
{
if
(
decision
!=
MVMap
.
Decision
.
ABORT
||
blockingTransaction
==
null
)
{
transaction
.
blockingMap
=
null
;
transaction
.
blockingKey
=
null
;
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
V
res
=
result
==
null
?
null
:
(
V
)
result
.
getCurrentValue
();
V
res
=
result
==
null
?
null
:
(
V
)
result
.
getCurrentValue
();
return
res
;
return
res
;
}
}
decisionMaker
.
reset
();
decisionMaker
.
reset
();
transaction
.
blockingMap
=
map
;
}
while
(
blockingTransaction
.
sequenceNum
>
sequenceNumWhenStarted
||
transaction
.
waitFor
(
blockingTransaction
,
map
,
key
));
transaction
.
blockingKey
=
key
;
}
while
(
blockingTransaction
.
sequenceNum
>
sequenceNumWhenStarted
||
transaction
.
waitFor
(
blockingTransaction
));
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TRANSACTION_LOCKED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TRANSACTION_LOCKED
,
"Map entry <{0}> with key <{1}> and value {2} is locked by tx {3} and can not be updated by tx {4}"
"Map entry <{0}> with key <{1}> and value {2} is locked by tx {3} and can not be updated by tx {4}"
...
@@ -669,8 +675,8 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -669,8 +675,8 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
private
final
boolean
includeAllUncommitted
;
private
final
boolean
includeAllUncommitted
;
private
X
current
;
private
X
current
;
protected
TMIterator
(
TransactionMap
<
K
,?>
transactionMap
,
K
from
,
K
to
,
boolean
includeAllUncommitted
)
{
TMIterator
(
TransactionMap
<
K
,?>
transactionMap
,
K
from
,
K
to
,
boolean
includeAllUncommitted
)
{
Transaction
transaction
=
transactionMap
.
transaction
;
Transaction
transaction
=
transactionMap
.
getTransaction
()
;
this
.
transactionId
=
transaction
.
transactionId
;
this
.
transactionId
=
transaction
.
transactionId
;
TransactionStore
store
=
transaction
.
store
;
TransactionStore
store
=
transaction
.
store
;
MVMap
<
K
,
VersionedValue
>
map
=
transactionMap
.
map
;
MVMap
<
K
,
VersionedValue
>
map
=
transactionMap
.
map
;
...
@@ -683,7 +689,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
...
@@ -683,7 +689,7 @@ public class TransactionMap<K, V> extends AbstractMap<K, V> {
MVMap
.
RootReference
mapRootReference
;
MVMap
.
RootReference
mapRootReference
;
do
{
do
{
committingTransactions
=
store
.
committingTransactions
.
get
();
committingTransactions
=
store
.
committingTransactions
.
get
();
mapRootReference
=
map
.
g
etRoot
();
mapRootReference
=
map
.
flushAndG
etRoot
();
}
while
(
committingTransactions
!=
store
.
committingTransactions
.
get
());
}
while
(
committingTransactions
!=
store
.
committingTransactions
.
get
());
// Now we have a snapshot, where mapRootReference points to state of the map
// Now we have a snapshot, where mapRootReference points to state of the map
// and committingTransactions mask tells us which of seemingly uncommitted changes
// and committingTransactions mask tells us which of seemingly uncommitted changes
...
...
h2/src/main/org/h2/mvstore/tx/TransactionStore.java
浏览文件 @
422f2826
...
@@ -390,7 +390,7 @@ public class TransactionStore {
...
@@ -390,7 +390,7 @@ public class TransactionStore {
*/
*/
long
addUndoLogRecord
(
int
transactionId
,
long
logId
,
Object
[]
undoLogRecord
)
{
long
addUndoLogRecord
(
int
transactionId
,
long
logId
,
Object
[]
undoLogRecord
)
{
MVMap
<
Long
,
Object
[]>
undoLog
=
undoLogs
[
transactionId
];
MVMap
<
Long
,
Object
[]>
undoLog
=
undoLogs
[
transactionId
];
L
ong
undoKey
=
getOperationId
(
transactionId
,
logId
);
l
ong
undoKey
=
getOperationId
(
transactionId
,
logId
);
if
(
logId
==
0
&&
!
undoLog
.
isEmpty
())
{
if
(
logId
==
0
&&
!
undoLog
.
isEmpty
())
{
throw
DataUtils
.
newIllegalStateException
(
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TOO_MANY_OPEN_TRANSACTIONS
,
DataUtils
.
ERROR_TOO_MANY_OPEN_TRANSACTIONS
,
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论