Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
a77eb02a
提交
a77eb02a
authored
3月 28, 2018
作者:
andrei
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
remove batch API for now
fix issue #999
上级
45a1bba8
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
156 行增加
和
307 行删除
+156
-307
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+147
-286
MVPrimaryIndex.java
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
+9
-11
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+0
-10
没有找到文件。
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
a77eb02a
...
@@ -21,14 +21,8 @@ import org.h2.mvstore.type.StringDataType;
...
@@ -21,14 +21,8 @@ import org.h2.mvstore.type.StringDataType;
/**
/**
* A stored map.
* A stored map.
* <p>
* <p>
*
Read
operations can happen concurrently with all other
*
All read and write
operations can happen concurrently with all other
* operations, without risk of corruption.
* operations, without risk of corruption.
* <p>
* Write operations first read the relevant area from disk to memory
* concurrently, and only then modify the data. The in-memory part of write
* operations is synchronized. For scalable concurrent in-memory write
* operations, the map should be split into multiple smaller sub-maps that are
* then synchronized independently.
*
*
* @param <K> the key class
* @param <K> the key class
* @param <V> the value class
* @param <V> the value class
...
@@ -887,7 +881,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -887,7 +881,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* Forget those old versions that are no longer needed.
* Forget those old versions that are no longer needed.
* @param rootReference to inspect
* @param rootReference to inspect
*/
*/
void
removeUnusedOldVersions
(
RootReference
rootReference
)
{
private
void
removeUnusedOldVersions
(
RootReference
rootReference
)
{
long
oldest
=
store
.
getOldestVersionToKeep
();
long
oldest
=
store
.
getOldestVersionToKeep
();
// We are trying to keep at least one previous version (if any) here.
// We are trying to keep at least one previous version (if any) here.
// This is not really necessary, just need to mimic existing
// This is not really necessary, just need to mimic existing
...
@@ -1129,7 +1123,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1129,7 +1123,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return
Page
.
createEmptyLeaf
(
this
);
return
Page
.
createEmptyLeaf
(
this
);
}
}
p
ublic
Page
createEmptyNode
()
{
p
rotected
Page
createEmptyNode
()
{
return
Page
.
createEmptyNode
(
this
);
return
Page
.
createEmptyNode
(
this
);
}
}
...
@@ -1404,86 +1398,83 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1404,86 +1398,83 @@ public class MVMap<K, V> extends AbstractMap<K, V>
}
}
}
}
public
interface
EntryProcessor
<
K
,
V
>
{
public
enum
Decision
{
ABORT
,
REMOVE
,
PUT
}
boolean
process
(
K
key
,
V
value
);
}
@SuppressWarnings
(
"unchecked"
)
public
abstract
static
class
DecisionMaker
<
V
>
public
static
<
K
,
V
>
void
process
(
Page
root
,
K
from
,
EntryProcessor
<
K
,
V
>
entryProcessor
)
{
{
CursorPos
cursorPos
=
Cursor
.
traverseDown
(
root
,
from
);
public
static
final
DecisionMaker
<
Object
>
DEFAULT
=
new
DecisionMaker
<
Object
>()
{
CursorPos
keeper
=
null
;
@Override
while
(
true
)
{
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
Page
page
=
cursorPos
.
page
;
return
providedValue
==
null
?
Decision
.
REMOVE
:
Decision
.
PUT
;
int
index
=
cursorPos
.
index
;
if
(
index
>=
(
page
.
isLeaf
()
?
page
.
getKeyCount
()
:
root
.
map
.
getChildPageCount
(
page
)))
{
CursorPos
tmp
=
cursorPos
;
cursorPos
=
cursorPos
.
parent
;
tmp
.
parent
=
keeper
;
keeper
=
tmp
;
if
(
cursorPos
==
null
)
{
return
;
}
}
else
{
while
(!
page
.
isLeaf
())
{
page
=
page
.
getChildPage
(
index
);
if
(
keeper
==
null
)
{
cursorPos
=
new
CursorPos
(
page
,
0
,
cursorPos
);
}
else
{
CursorPos
tmp
=
keeper
;
keeper
=
keeper
.
parent
;
tmp
.
parent
=
cursorPos
;
tmp
.
page
=
page
;
tmp
.
index
=
0
;
cursorPos
=
tmp
;
}
index
=
0
;
}
K
key
=
(
K
)
page
.
getKey
(
index
);
V
value
=
(
V
)
page
.
getValue
(
index
);
if
(
entryProcessor
.
process
(
key
,
value
))
{
return
;
}
}
}
++
cursorPos
.
index
;
}
}
@Override
public
String
toString
()
{
return
"default"
;
}
};
public
interface
LeafProcessor
public
static
final
DecisionMaker
<
Object
>
PUT
=
new
DecisionMaker
<
Object
>()
{
{
@Override
CursorPos
locate
(
Page
rootPage
);
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
Page
[]
process
(
CursorPos
pos
);
return
Decision
.
PUT
;
CursorPos
locateNext
(
Page
rootPage
);
}
void
stepBack
();
void
confirmSuccess
();
@Override
public
String
toString
()
{
return
"put"
;
}
};
public
static
final
DecisionMaker
<
Object
>
REMOVE
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
Decision
.
REMOVE
;
}
@Override
public
String
toString
()
{
return
"remove"
;
}
};
private
static
final
DecisionMaker
<
Object
>
IF_ABSENT
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
existingValue
==
null
?
Decision
.
PUT
:
Decision
.
ABORT
;
}
@Override
public
String
toString
()
{
return
"if_absent"
;
}
};
private
static
final
DecisionMaker
<
Object
>
IF_PRESENT
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
existingValue
!=
null
?
Decision
.
PUT
:
Decision
.
ABORT
;
}
@Override
public
String
toString
()
{
return
"if_present"
;
}
};
public
abstract
Decision
decide
(
V
existingValue
,
V
providedValue
);
public
<
T
extends
V
>
T
selectValue
(
T
existingValue
,
T
providedValue
)
{
return
providedValue
;
}
public
void
reset
()
{}
}
}
public
final
void
operateBatch
(
LeafProcessor
processo
r
)
{
public
V
operate
(
K
key
,
V
value
,
DecisionMaker
<?
super
V
>
decisionMake
r
)
{
beforeWrite
();
beforeWrite
();
int
attempt
=
0
;
int
attempt
=
0
;
RootReference
rootReference
=
getRoot
();
RootReference
oldRootReference
=
null
;
RootReference
oldRootReference
=
null
;
CursorPos
pos
;
while
(
true
)
{
while
(
true
)
{
if
(
rootReference
.
semaphore
)
{
RootReference
rootReference
=
getRoot
();
Thread
.
yield
();
rootReference
=
getRoot
();
continue
;
}
pos
=
processor
.
locate
(
rootReference
.
root
);
if
(
pos
==
null
)
{
return
;
}
Page
replacement
[]
=
processor
.
process
(
pos
);
if
(
replacement
==
null
)
{
if
(
rootReference
!=
getRoot
())
{
processor
.
stepBack
();
rootReference
=
getRoot
();
continue
;
}
return
;
}
int
contention
=
0
;
int
contention
=
0
;
if
(
oldRootReference
!=
null
)
{
if
(
oldRootReference
!=
null
)
{
long
updateAttemptCounter
=
rootReference
.
updateAttemptCounter
-
oldRootReference
.
updateAttemptCounter
;
long
updateAttemptCounter
=
rootReference
.
updateAttemptCounter
-
oldRootReference
.
updateAttemptCounter
;
...
@@ -1495,67 +1486,85 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1495,67 +1486,85 @@ public class MVMap<K, V> extends AbstractMap<K, V>
}
}
oldRootReference
=
rootReference
;
oldRootReference
=
rootReference
;
++
attempt
;
++
attempt
;
CursorPos
tip
=
pos
;
CursorPos
pos
=
traverseDown
(
rootReference
.
root
,
key
)
;
Page
p
=
pos
.
page
;
Page
p
=
pos
.
page
;
int
index
=
pos
.
index
;
CursorPos
tip
=
pos
;
pos
=
pos
.
parent
;
pos
=
pos
.
parent
;
final
V
result
=
index
<
0
?
null
:
(
V
)
p
.
getValue
(
index
);
Decision
decision
=
decisionMaker
.
decide
(
result
,
value
);
int
unsavedMemory
=
0
;
int
unsavedMemory
=
0
;
boolean
needUnlock
=
false
;
boolean
needUnlock
=
false
;
try
{
try
{
if
(
attempt
>
4
&&
!(
needUnlock
=
lockRoot
(
processor
,
rootReference
,
attempt
,
contention
)))
{
switch
(
decision
)
{
processor
.
stepBack
();
case
ABORT:
rootReference
=
getRoot
();
if
(
rootReference
!=
getRoot
())
{
continue
;
decisionMaker
.
reset
();
}
continue
;
int
index
;
}
switch
(
replacement
.
length
)
{
return
result
;
case
0
:
case
REMOVE:
{
if
(
pos
!=
null
)
{
if
(
index
<
0
)
{
p
=
pos
.
page
;
return
null
;
index
=
pos
.
index
;
}
pos
=
pos
.
parent
;
if
(
attempt
>
2
&&
!(
needUnlock
=
lockRoot
(
decisionMaker
,
rootReference
,
attempt
,
contention
)))
{
assert
p
.
getKeyCount
()
>
0
;
continue
;
if
(
p
.
getKeyCount
()
==
1
)
{
}
assert
index
<=
1
;
if
(
p
.
getTotalCount
()
==
1
&&
pos
!=
null
)
{
p
=
p
.
getChildPage
(
1
-
index
);
p
=
pos
.
page
;
break
;
index
=
pos
.
index
;
pos
=
pos
.
parent
;
if
(
p
.
getKeyCount
()
==
1
)
{
assert
index
<=
1
;
p
=
p
.
getChildPage
(
1
-
index
);
break
;
}
assert
p
.
getKeyCount
()
>
1
;
}
}
p
=
p
.
copy
();
p
=
p
.
copy
();
p
.
remove
(
index
);
p
.
remove
(
index
);
}
else
{
break
;
p
=
createEmptyLeaf
();
}
}
break
;
case
PUT:
{
case
1
:
if
(
attempt
>
2
&&
!(
needUnlock
=
lockRoot
(
decisionMaker
,
rootReference
,
attempt
,
contention
)))
{
p
=
replacement
[
0
];
continue
;
int
keyCount
;
while
((
keyCount
=
p
.
getKeyCount
())
>
store
.
getKeysPerPage
()
||
p
.
getMemory
()
>
store
.
getMaxPageSize
()
&&
keyCount
>
(
p
.
isLeaf
()
?
1
:
2
))
{
long
totalCount
=
p
.
getTotalCount
();
int
at
=
keyCount
>>
1
;
Object
k
=
p
.
getKey
(
at
);
Page
split
=
p
.
split
(
at
);
unsavedMemory
+=
p
.
getMemory
();
unsavedMemory
+=
split
.
getMemory
();
if
(
pos
==
null
)
{
Object
keys
[]
=
{
k
};
Page
.
PageReference
children
[]
=
{
new
Page
.
PageReference
(
p
),
new
Page
.
PageReference
(
split
)
};
p
=
Page
.
create
(
this
,
keys
,
null
,
children
,
totalCount
,
0
);
break
;
}
}
Page
c
=
p
;
value
=
decisionMaker
.
selectValue
(
result
,
value
);
p
=
pos
.
page
;
index
=
pos
.
index
;
pos
=
pos
.
parent
;
p
=
p
.
copy
();
p
=
p
.
copy
();
p
.
setChild
(
index
,
split
);
if
(
index
<
0
)
{
p
.
insertNode
(
index
,
k
,
c
);
p
.
insertLeaf
(-
index
-
1
,
key
,
value
);
int
keyCount
;
while
((
keyCount
=
p
.
getKeyCount
())
>
store
.
getKeysPerPage
()
||
p
.
getMemory
()
>
store
.
getMaxPageSize
()
&&
keyCount
>
(
p
.
isLeaf
()
?
1
:
2
))
{
long
totalCount
=
p
.
getTotalCount
();
int
at
=
keyCount
>>
1
;
Object
k
=
p
.
getKey
(
at
);
Page
split
=
p
.
split
(
at
);
unsavedMemory
+=
p
.
getMemory
();
unsavedMemory
+=
split
.
getMemory
();
if
(
pos
==
null
)
{
Object
keys
[]
=
{
k
};
Page
.
PageReference
children
[]
=
{
new
Page
.
PageReference
(
p
),
new
Page
.
PageReference
(
split
)
};
p
=
Page
.
create
(
this
,
keys
,
null
,
children
,
totalCount
,
0
);
break
;
}
Page
c
=
p
;
p
=
pos
.
page
;
index
=
pos
.
index
;
pos
=
pos
.
parent
;
p
=
p
.
copy
();
p
.
setChild
(
index
,
split
);
p
.
insertNode
(
index
,
k
,
c
);
}
}
else
{
p
.
setValue
(
index
,
value
);
}
break
;
}
}
default
:
break
;
}
}
unsavedMemory
+=
p
.
getMemory
();
unsavedMemory
+=
p
.
getMemory
();
while
(
pos
!=
null
)
{
while
(
pos
!=
null
)
{
...
@@ -1566,15 +1575,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1566,15 +1575,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
unsavedMemory
+=
p
.
getMemory
();
unsavedMemory
+=
p
.
getMemory
();
pos
=
pos
.
parent
;
pos
=
pos
.
parent
;
}
}
if
((
pos
=
processor
.
locateNext
(
p
))
!=
null
)
{
continue
;
// Multi-node batch operation
}
if
(
needUnlock
)
{
if
(
needUnlock
)
{
unlockRoot
(
p
,
attempt
);
unlockRoot
(
p
,
attempt
);
needUnlock
=
false
;
needUnlock
=
false
;
}
else
if
(!
updateRoot
(
rootReference
,
p
,
attempt
))
{
}
else
if
(!
updateRoot
(
rootReference
,
p
,
attempt
))
{
processor
.
stepBack
();
decisionMaker
.
reset
();
rootReference
=
getRoot
();
continue
;
continue
;
}
}
while
(
tip
!=
null
)
{
while
(
tip
!=
null
)
{
...
@@ -1584,8 +1589,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1584,8 +1589,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
if
(
store
.
getFileStore
()
!=
null
)
{
if
(
store
.
getFileStore
()
!=
null
)
{
store
.
registerUnsavedPage
(
unsavedMemory
);
store
.
registerUnsavedPage
(
unsavedMemory
);
}
}
processor
.
confirmSuccess
();
return
result
;
break
;
}
finally
{
}
finally
{
if
(
needUnlock
)
{
if
(
needUnlock
)
{
unlockRoot
(
rootReference
.
root
,
attempt
);
unlockRoot
(
rootReference
.
root
,
attempt
);
...
@@ -1594,12 +1598,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1594,12 +1598,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
}
}
}
}
private
boolean
lockRoot
(
LeafProcessor
processo
r
,
RootReference
rootReference
,
private
boolean
lockRoot
(
DecisionMaker
<?
super
V
>
decisionMake
r
,
RootReference
rootReference
,
int
attempt
,
int
contention
)
{
int
attempt
,
int
contention
)
{
boolean
success
=
root
.
compareAndSet
(
rootReference
,
new
RootReference
(
rootReference
)
);
boolean
success
=
lockRoot
(
rootReference
);
if
(!
success
)
{
if
(!
success
)
{
processor
.
stepBack
();
decisionMaker
.
reset
();
if
(
attempt
>
8
)
{
if
(
attempt
>
4
)
{
if
(
attempt
<=
24
)
{
if
(
attempt
<=
24
)
{
Thread
.
yield
();
Thread
.
yield
();
}
else
{
}
else
{
...
@@ -1612,6 +1616,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1612,6 +1616,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return
success
;
return
success
;
}
}
private
boolean
lockRoot
(
RootReference
rootReference
)
{
return
!
rootReference
.
semaphore
&&
root
.
compareAndSet
(
rootReference
,
new
RootReference
(
rootReference
));
}
private
void
unlockRoot
(
Page
newRoot
,
int
attempt
)
{
private
void
unlockRoot
(
Page
newRoot
,
int
attempt
)
{
boolean
success
;
boolean
success
;
do
{
do
{
...
@@ -1635,154 +1644,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -1635,154 +1644,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return
new
CursorPos
(
p
,
p
.
binarySearch
(
key
),
pos
);
return
new
CursorPos
(
p
,
p
.
binarySearch
(
key
),
pos
);
}
}
public
static
final
class
SingleDecisionMaker
<
K
,
V
>
implements
LeafProcessor
{
private
final
DecisionMaker
<?
super
V
>
decisionMaker
;
private
final
K
key
;
private
final
V
value
;
private
V
result
;
public
SingleDecisionMaker
(
K
key
,
V
value
,
DecisionMaker
<?
super
V
>
decisionMaker
)
{
this
.
decisionMaker
=
decisionMaker
;
this
.
key
=
key
;
this
.
value
=
value
;
}
@Override
public
CursorPos
locate
(
Page
rootPage
)
{
return
traverseDown
(
rootPage
,
key
);
}
@Override
public
CursorPos
locateNext
(
Page
rootPage
)
{
return
null
;
}
@Override
public
void
stepBack
()
{
decisionMaker
.
reset
();
}
@Override
public
void
confirmSuccess
()
{}
@SuppressWarnings
(
"unchecked"
)
@Override
public
Page
[]
process
(
CursorPos
pos
)
{
Page
leaf
=
pos
.
page
;
int
index
=
pos
.
index
;
result
=
index
<
0
?
null
:
(
V
)
leaf
.
getValue
(
index
);
Decision
decision
=
decisionMaker
.
decide
(
result
,
value
);
switch
(
decision
)
{
case
ABORT:
return
null
;
case
REMOVE:
{
if
(
index
<
0
)
{
return
null
;
}
if
(
leaf
.
getTotalCount
()
==
1
)
{
return
new
Page
[
0
];
}
leaf
=
leaf
.
copy
();
leaf
.
remove
(
index
);
return
new
Page
[]
{
leaf
};
}
case
PUT:
{
V
v
=
decisionMaker
.
selectValue
(
result
,
value
);
leaf
=
leaf
.
copy
();
if
(
index
<
0
)
{
leaf
.
insertLeaf
(-
index
-
1
,
key
,
v
);
}
else
{
leaf
.
setValue
(
index
,
v
);
}
return
new
Page
[]
{
leaf
};
}
default
:
return
null
;
}
}
public
V
getResult
()
{
return
result
;
}
}
public
enum
Decision
{
ABORT
,
REMOVE
,
PUT
}
public
abstract
static
class
DecisionMaker
<
V
>
{
public
static
final
DecisionMaker
<
Object
>
DEFAULT
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
providedValue
==
null
?
Decision
.
REMOVE
:
Decision
.
PUT
;
}
@Override
public
String
toString
()
{
return
"default"
;
}
};
public
static
final
DecisionMaker
<
Object
>
PUT
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
Decision
.
PUT
;
}
@Override
public
String
toString
()
{
return
"put"
;
}
};
public
static
final
DecisionMaker
<
Object
>
REMOVE
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
Decision
.
REMOVE
;
}
@Override
public
String
toString
()
{
return
"remove"
;
}
};
private
static
final
DecisionMaker
<
Object
>
IF_ABSENT
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
existingValue
==
null
?
Decision
.
PUT
:
Decision
.
ABORT
;
}
@Override
public
String
toString
()
{
return
"if_absent"
;
}
};
private
static
final
DecisionMaker
<
Object
>
IF_PRESENT
=
new
DecisionMaker
<
Object
>()
{
@Override
public
Decision
decide
(
Object
existingValue
,
Object
providedValue
)
{
return
existingValue
!=
null
?
Decision
.
PUT
:
Decision
.
ABORT
;
}
@Override
public
String
toString
()
{
return
"if_present"
;
}
};
public
abstract
Decision
decide
(
V
existingValue
,
V
providedValue
);
public
<
T
extends
V
>
T
selectValue
(
T
existingValue
,
T
providedValue
)
{
return
providedValue
;
}
public
void
reset
()
{}
}
public
V
operate
(
K
key
,
V
value
,
DecisionMaker
<?
super
V
>
decisionMaker
)
{
SingleDecisionMaker
<
K
,
V
>
processor
=
new
SingleDecisionMaker
<>(
key
,
value
,
decisionMaker
);
operateBatch
(
processor
);
return
processor
.
getResult
();
}
private
static
final
class
EqualsDecisionMaker
<
V
>
extends
DecisionMaker
<
V
>
{
private
static
final
class
EqualsDecisionMaker
<
V
>
extends
DecisionMaker
<
V
>
{
private
final
DataType
dataType
;
private
final
DataType
dataType
;
private
final
V
expectedValue
;
private
final
V
expectedValue
;
...
...
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
浏览文件 @
a77eb02a
...
@@ -114,18 +114,16 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -114,18 +114,16 @@ public class MVPrimaryIndex extends BaseIndex {
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
TransactionMap
<
Value
,
Value
>
map
=
getMap
(
session
);
Value
key
=
ValueLong
.
get
(
row
.
getKey
());
Value
key
=
ValueLong
.
get
(
row
.
getKey
());
Value
old
=
map
.
getLatest
(
key
);
if
(
old
!=
null
)
{
String
sql
=
"PRIMARY KEY ON "
+
table
.
getSQL
();
if
(
mainIndexColumn
>=
0
&&
mainIndexColumn
<
indexColumns
.
length
)
{
sql
+=
"("
+
indexColumns
[
mainIndexColumn
].
getSQL
()
+
")"
;
}
DbException
e
=
DbException
.
get
(
ErrorCode
.
DUPLICATE_KEY_1
,
sql
);
e
.
setSource
(
this
);
throw
e
;
}
try
{
try
{
map
.
put
(
key
,
ValueArray
.
get
(
row
.
getValueList
()));
if
(
map
.
put
(
key
,
ValueArray
.
get
(
row
.
getValueList
()))
!=
null
)
{
String
sql
=
"PRIMARY KEY ON "
+
table
.
getSQL
();
if
(
mainIndexColumn
>=
0
&&
mainIndexColumn
<
indexColumns
.
length
)
{
sql
+=
"("
+
indexColumns
[
mainIndexColumn
].
getSQL
()
+
")"
;
}
DbException
e
=
DbException
.
get
(
ErrorCode
.
DUPLICATE_KEY_1
,
sql
);
e
.
setSource
(
this
);
throw
e
;
}
}
catch
(
IllegalStateException
e
)
{
}
catch
(
IllegalStateException
e
)
{
throw
mvTable
.
convertException
(
e
);
throw
mvTable
.
convertException
(
e
);
}
}
...
...
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
a77eb02a
...
@@ -1198,16 +1198,6 @@ public class TransactionStore {
...
@@ -1198,16 +1198,6 @@ public class TransactionStore {
return
get
(
key
,
readLogId
);
return
get
(
key
,
readLogId
);
}
}
/**
* Get the most recent value for the given key.
*
* @param key the key
* @return the value or null
*/
public
V
getLatest
(
K
key
)
{
return
get
(
key
,
Long
.
MAX_VALUE
);
}
/**
/**
* Whether the map contains the key.
* Whether the map contains the key.
*
*
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论