Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
99d6c3ee
提交
99d6c3ee
authored
7月 23, 2015
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Formatting
上级
1f55186b
显示空白字符变更
内嵌
并排
正在显示
24 个修改的文件
包含
193 行增加
和
87 行删除
+193
-87
ScriptBase.java
h2/src/main/org/h2/command/dml/ScriptBase.java
+1
-1
Engine.java
h2/src/main/org/h2/engine/Engine.java
+3
-1
SessionRemote.java
h2/src/main/org/h2/engine/SessionRemote.java
+2
-2
SysProperties.java
h2/src/main/org/h2/engine/SysProperties.java
+8
-0
Function.java
h2/src/main/org/h2/expression/Function.java
+1
-1
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+1
-1
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+1
-1
MVTable.java
h2/src/main/org/h2/mvstore/db/MVTable.java
+61
-18
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+14
-0
Sequence.java
h2/src/main/org/h2/schema/Sequence.java
+5
-2
DataHandler.java
h2/src/main/org/h2/store/DataHandler.java
+2
-2
FilePathMem.java
h2/src/main/org/h2/store/fs/FilePathMem.java
+6
-0
Column.java
h2/src/main/org/h2/table/Column.java
+2
-1
Recover.java
h2/src/main/org/h2/tools/Recover.java
+1
-1
Server.java
h2/src/main/org/h2/tools/Server.java
+2
-0
DebuggingThreadLocal.java
h2/src/main/org/h2/util/DebuggingThreadLocal.java
+6
-5
ThreadDeadlockDetector.java
h2/src/main/org/h2/util/ThreadDeadlockDetector.java
+35
-31
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+1
-1
TestCompatibilityOracle.java
h2/src/test/org/h2/test/db/TestCompatibilityOracle.java
+4
-2
TestFunctions.java
h2/src/test/org/h2/test/db/TestFunctions.java
+2
-3
TestReorderWrites.java
h2/src/test/org/h2/test/poweroff/TestReorderWrites.java
+1
-1
TestValueHashMap.java
h2/src/test/org/h2/test/unit/TestValueHashMap.java
+1
-1
TestValueMemory.java
h2/src/test/org/h2/test/unit/TestValueMemory.java
+1
-1
FilePathReorderWrites.java
h2/src/test/org/h2/test/utils/FilePathReorderWrites.java
+32
-11
没有找到文件。
h2/src/main/org/h2/command/dml/ScriptBase.java
浏览文件 @
99d6c3ee
h2/src/main/org/h2/engine/Engine.java
浏览文件 @
99d6c3ee
...
@@ -36,8 +36,10 @@ public class Engine implements SessionFactory {
...
@@ -36,8 +36,10 @@ public class Engine implements SessionFactory {
private
Engine
()
{
private
Engine
()
{
// use getInstance()
// use getInstance()
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
ThreadDeadlockDetector
.
init
();
ThreadDeadlockDetector
.
init
();
}
}
}
public
static
Engine
getInstance
()
{
public
static
Engine
getInstance
()
{
return
INSTANCE
;
return
INSTANCE
;
...
...
h2/src/main/org/h2/engine/SessionRemote.java
浏览文件 @
99d6c3ee
h2/src/main/org/h2/engine/SysProperties.java
浏览文件 @
99d6c3ee
...
@@ -453,6 +453,14 @@ public class SysProperties {
...
@@ -453,6 +453,14 @@ public class SysProperties {
public
static
final
boolean
TRACE_IO
=
public
static
final
boolean
TRACE_IO
=
Utils
.
getProperty
(
"h2.traceIO"
,
false
);
Utils
.
getProperty
(
"h2.traceIO"
,
false
);
/**
* System property <code>h2.threadDeadlockDetector</code>
* (default: false).<br />
* Detect thread deadlocks in a background thread.
*/
public
static
final
boolean
THREAD_DEADLOCK_DETECTOR
=
Utils
.
getProperty
(
"h2.threadDeadlockDetector"
,
false
);
/**
/**
* System property <code>h2.implicitRelativePath</code>
* System property <code>h2.implicitRelativePath</code>
* (default: true for version 1.3, false for version 1.4).<br />
* (default: true for version 1.3, false for version 1.4).<br />
...
...
h2/src/main/org/h2/expression/Function.java
浏览文件 @
99d6c3ee
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
99d6c3ee
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
99d6c3ee
...
@@ -2314,7 +2314,7 @@ public class MVStore {
...
@@ -2314,7 +2314,7 @@ public class MVStore {
releaseWriteBuffer
(
buff
);
releaseWriteBuffer
(
buff
);
// only really needed if we remove many chunks, when writes are
// only really needed if we remove many chunks, when writes are
// re-ordered - but we do it always, because rollback is not
// re-ordered - but we do it always, because rollback is not
// performance critic
i
al
// performance critical
sync
();
sync
();
}
}
lastChunk
=
keep
;
lastChunk
=
keep
;
...
...
h2/src/main/org/h2/mvstore/db/MVTable.java
浏览文件 @
99d6c3ee
...
@@ -49,9 +49,32 @@ import org.h2.value.Value;
...
@@ -49,9 +49,32 @@ import org.h2.value.Value;
*/
*/
public
class
MVTable
extends
TableBase
{
public
class
MVTable
extends
TableBase
{
public
static
final
DebuggingThreadLocal
<
String
>
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<
String
>();
/**
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
EXCLUSIVE_LOCKS
=
new
DebuggingThreadLocal
<
ArrayList
<
String
>>();
* The table name this thread is waiting to lock.
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
SHARED_LOCKS
=
new
DebuggingThreadLocal
<
ArrayList
<
String
>>();
*/
public
static
final
DebuggingThreadLocal
<
String
>
WAITING_FOR_LOCK
;
/**
* The table names this thread has exclusively locked.
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
EXCLUSIVE_LOCKS
;
/**
* The tables names this thread has a shared lock on.
*/
public
static
final
DebuggingThreadLocal
<
ArrayList
<
String
>>
SHARED_LOCKS
;
static
{
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
=
new
DebuggingThreadLocal
<
String
>();
EXCLUSIVE_LOCKS
=
new
DebuggingThreadLocal
<
ArrayList
<
String
>>();
SHARED_LOCKS
=
new
DebuggingThreadLocal
<
ArrayList
<
String
>>();
}
else
{
WAITING_FOR_LOCK
=
null
;
EXCLUSIVE_LOCKS
=
null
;
SHARED_LOCKS
=
null
;
}
}
private
MVPrimaryIndex
primaryIndex
;
private
MVPrimaryIndex
primaryIndex
;
private
final
ArrayList
<
Index
>
indexes
=
New
.
arrayList
();
private
final
ArrayList
<
Index
>
indexes
=
New
.
arrayList
();
...
@@ -136,13 +159,17 @@ public class MVTable extends TableBase {
...
@@ -136,13 +159,17 @@ public class MVTable extends TableBase {
return
true
;
return
true
;
}
}
session
.
setWaitForLock
(
this
,
Thread
.
currentThread
());
session
.
setWaitForLock
(
this
,
Thread
.
currentThread
());
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
.
set
(
getName
());
WAITING_FOR_LOCK
.
set
(
getName
());
}
waitingSessions
.
addLast
(
session
);
waitingSessions
.
addLast
(
session
);
try
{
try
{
doLock1
(
session
,
lockMode
,
exclusive
);
doLock1
(
session
,
lockMode
,
exclusive
);
}
finally
{
}
finally
{
session
.
setWaitForLock
(
null
,
null
);
session
.
setWaitForLock
(
null
,
null
);
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
WAITING_FOR_LOCK
.
remove
();
WAITING_FOR_LOCK
.
remove
();
}
waitingSessions
.
remove
(
session
);
waitingSessions
.
remove
(
session
);
}
}
}
}
...
@@ -226,19 +253,23 @@ public class MVTable extends TableBase {
...
@@ -226,19 +253,23 @@ public class MVTable extends TableBase {
traceLock
(
session
,
exclusive
,
"added for"
);
traceLock
(
session
,
exclusive
,
"added for"
);
session
.
addLock
(
this
);
session
.
addLock
(
this
);
lockExclusiveSession
=
session
;
lockExclusiveSession
=
session
;
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
EXCLUSIVE_LOCKS
.
get
()
==
null
)
{
if
(
EXCLUSIVE_LOCKS
.
get
()
==
null
)
{
EXCLUSIVE_LOCKS
.
set
(
new
ArrayList
<
String
>());
EXCLUSIVE_LOCKS
.
set
(
new
ArrayList
<
String
>());
}
}
EXCLUSIVE_LOCKS
.
get
().
add
(
getName
());
EXCLUSIVE_LOCKS
.
get
().
add
(
getName
());
}
return
true
;
return
true
;
}
else
if
(
lockSharedSessions
.
size
()
==
1
&&
}
else
if
(
lockSharedSessions
.
size
()
==
1
&&
lockSharedSessions
.
containsKey
(
session
))
{
lockSharedSessions
.
containsKey
(
session
))
{
traceLock
(
session
,
exclusive
,
"add (upgraded) for "
);
traceLock
(
session
,
exclusive
,
"add (upgraded) for "
);
lockExclusiveSession
=
session
;
lockExclusiveSession
=
session
;
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
EXCLUSIVE_LOCKS
.
get
()
==
null
)
{
if
(
EXCLUSIVE_LOCKS
.
get
()
==
null
)
{
EXCLUSIVE_LOCKS
.
set
(
new
ArrayList
<
String
>());
EXCLUSIVE_LOCKS
.
set
(
new
ArrayList
<
String
>());
}
}
EXCLUSIVE_LOCKS
.
get
().
add
(
getName
());
EXCLUSIVE_LOCKS
.
get
().
add
(
getName
());
}
return
true
;
return
true
;
}
}
}
}
...
@@ -260,11 +291,13 @@ public class MVTable extends TableBase {
...
@@ -260,11 +291,13 @@ public class MVTable extends TableBase {
traceLock
(
session
,
exclusive
,
"ok"
);
traceLock
(
session
,
exclusive
,
"ok"
);
session
.
addLock
(
this
);
session
.
addLock
(
this
);
lockSharedSessions
.
put
(
session
,
session
);
lockSharedSessions
.
put
(
session
,
session
);
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
SHARED_LOCKS
.
get
()
==
null
)
{
if
(
SHARED_LOCKS
.
get
()
==
null
)
{
SHARED_LOCKS
.
set
(
new
ArrayList
<
String
>());
SHARED_LOCKS
.
set
(
new
ArrayList
<
String
>());
}
}
SHARED_LOCKS
.
get
().
add
(
getName
());
SHARED_LOCKS
.
get
().
add
(
getName
());
}
}
}
return
true
;
return
true
;
}
}
}
}
...
@@ -377,17 +410,21 @@ public class MVTable extends TableBase {
...
@@ -377,17 +410,21 @@ public class MVTable extends TableBase {
traceLock
(
s
,
lockExclusiveSession
==
s
,
"unlock"
);
traceLock
(
s
,
lockExclusiveSession
==
s
,
"unlock"
);
if
(
lockExclusiveSession
==
s
)
{
if
(
lockExclusiveSession
==
s
)
{
lockExclusiveSession
=
null
;
lockExclusiveSession
=
null
;
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
EXCLUSIVE_LOCKS
.
get
()
!=
null
)
{
if
(
EXCLUSIVE_LOCKS
.
get
()
!=
null
)
{
EXCLUSIVE_LOCKS
.
get
().
remove
(
getName
());
EXCLUSIVE_LOCKS
.
get
().
remove
(
getName
());
}
}
}
}
}
synchronized
(
getLockSyncObject
())
{
synchronized
(
getLockSyncObject
())
{
if
(
lockSharedSessions
.
size
()
>
0
)
{
if
(
lockSharedSessions
.
size
()
>
0
)
{
lockSharedSessions
.
remove
(
s
);
lockSharedSessions
.
remove
(
s
);
if
(
SysProperties
.
THREAD_DEADLOCK_DETECTOR
)
{
if
(
SHARED_LOCKS
.
get
()
!=
null
)
{
if
(
SHARED_LOCKS
.
get
()
!=
null
)
{
SHARED_LOCKS
.
get
().
remove
(
getName
());
SHARED_LOCKS
.
get
().
remove
(
getName
());
}
}
}
}
}
if
(!
waitingSessions
.
isEmpty
())
{
if
(!
waitingSessions
.
isEmpty
())
{
getLockSyncObject
().
notifyAll
();
getLockSyncObject
().
notifyAll
();
}
}
...
@@ -849,6 +886,12 @@ public class MVTable extends TableBase {
...
@@ -849,6 +886,12 @@ public class MVTable extends TableBase {
}
}
}
}
/**
* Convert the illegal state exception to a database exception.
*
* @param e the illegal state exception
* @return the database exception
*/
DbException
convertException
(
IllegalStateException
e
)
{
DbException
convertException
(
IllegalStateException
e
)
{
if
(
DataUtils
.
getErrorCode
(
e
.
getMessage
())
==
if
(
DataUtils
.
getErrorCode
(
e
.
getMessage
())
==
DataUtils
.
ERROR_TRANSACTION_LOCKED
)
{
DataUtils
.
ERROR_TRANSACTION_LOCKED
)
{
...
...
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
99d6c3ee
...
@@ -141,6 +141,13 @@ public class MVTableEngine implements TableEngine {
...
@@ -141,6 +141,13 @@ public class MVTableEngine implements TableEngine {
private
String
fileName
;
private
String
fileName
;
/**
* Open the store for this database.
*
* @param db the database
* @param builder the builder
* @param encrypted whether the store is encrypted
*/
void
open
(
Database
db
,
MVStore
.
Builder
builder
,
boolean
encrypted
)
{
void
open
(
Database
db
,
MVStore
.
Builder
builder
,
boolean
encrypted
)
{
this
.
encrypted
=
encrypted
;
this
.
encrypted
=
encrypted
;
try
{
try
{
...
@@ -161,6 +168,13 @@ public class MVTableEngine implements TableEngine {
...
@@ -161,6 +168,13 @@ public class MVTableEngine implements TableEngine {
}
}
}
}
/**
* Convert the illegal state exception to the correct database
* exception.
*
* @param e the illegal state exception
* @return the database exception
*/
DbException
convertIllegalStateException
(
IllegalStateException
e
)
{
DbException
convertIllegalStateException
(
IllegalStateException
e
)
{
int
errorCode
=
DataUtils
.
getErrorCode
(
e
.
getMessage
());
int
errorCode
=
DataUtils
.
getErrorCode
(
e
.
getMessage
());
if
(
errorCode
==
DataUtils
.
ERROR_FILE_CORRUPT
)
{
if
(
errorCode
==
DataUtils
.
ERROR_FILE_CORRUPT
)
{
...
...
h2/src/main/org/h2/schema/Sequence.java
浏览文件 @
99d6c3ee
...
@@ -33,8 +33,10 @@ public class Sequence extends SchemaObjectBase {
...
@@ -33,8 +33,10 @@ public class Sequence extends SchemaObjectBase {
private
long
maxValue
;
private
long
maxValue
;
private
boolean
cycle
;
private
boolean
cycle
;
private
boolean
belongsToTable
;
private
boolean
belongsToTable
;
/**
/**
* The last valueWithMargin we flushed. We do a little dance with this to avoid an ABBA deadlock.
* The last valueWithMargin we flushed. We do a little dance with this to
* avoid an ABBA deadlock.
*/
*/
private
long
lastFlushValueWithMargin
;
private
long
lastFlushValueWithMargin
;
...
@@ -289,6 +291,7 @@ public class Sequence extends SchemaObjectBase {
...
@@ -289,6 +291,7 @@ public class Sequence extends SchemaObjectBase {
* Flush the current value, including the margin, to disk.
* Flush the current value, including the margin, to disk.
*
*
* @param session the session
* @param session the session
* @param flushValueWithMargin whether to reserve more entries
*/
*/
public
void
flush
(
Session
session
,
long
flushValueWithMargin
)
{
public
void
flush
(
Session
session
,
long
flushValueWithMargin
)
{
if
(
session
==
null
||
!
database
.
isSysTableLockedBy
(
session
))
{
if
(
session
==
null
||
!
database
.
isSysTableLockedBy
(
session
))
{
...
...
h2/src/main/org/h2/store/DataHandler.java
浏览文件 @
99d6c3ee
h2/src/main/org/h2/store/fs/FilePathMem.java
浏览文件 @
99d6c3ee
...
@@ -202,6 +202,12 @@ public class FilePathMem extends FilePath {
...
@@ -202,6 +202,12 @@ public class FilePathMem extends FilePath {
return
name
.
equals
(
getScheme
()
+
":"
);
return
name
.
equals
(
getScheme
()
+
":"
);
}
}
/**
* Get the canonical path for this file name.
*
* @param fileName the file name
* @return the canonical path
*/
protected
static
String
getCanonicalPath
(
String
fileName
)
{
protected
static
String
getCanonicalPath
(
String
fileName
)
{
fileName
=
fileName
.
replace
(
'\\'
,
'/'
);
fileName
=
fileName
.
replace
(
'\\'
,
'/'
);
int
idx
=
fileName
.
indexOf
(
':'
)
+
1
;
int
idx
=
fileName
.
indexOf
(
':'
)
+
1
;
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
99d6c3ee
...
@@ -266,7 +266,8 @@ public class Column {
...
@@ -266,7 +266,8 @@ public class Column {
* @return the new or converted value
* @return the new or converted value
*/
*/
public
Value
validateConvertUpdateSequence
(
Session
session
,
Value
value
)
{
public
Value
validateConvertUpdateSequence
(
Session
session
,
Value
value
)
{
// take a local copy of defaultExpression to avoid holding the lock while calling getValue
// take a local copy of defaultExpression to avoid holding the lock
// while calling getValue
final
Expression
localDefaultExpression
;
final
Expression
localDefaultExpression
;
synchronized
(
this
)
{
synchronized
(
this
)
{
localDefaultExpression
=
defaultExpression
;
localDefaultExpression
=
defaultExpression
;
...
...
h2/src/main/org/h2/tools/Recover.java
浏览文件 @
99d6c3ee
h2/src/main/org/h2/tools/Server.java
浏览文件 @
99d6c3ee
...
@@ -437,6 +437,7 @@ public class Server extends Tool implements Runnable, ShutdownHandler {
...
@@ -437,6 +437,7 @@ public class Server extends Tool implements Runnable, ShutdownHandler {
* If no port is specified, the default port is used if possible,
* If no port is specified, the default port is used if possible,
* and if this port is already used, a random port is used.
* and if this port is already used, a random port is used.
* Use getPort() or getURL() after starting to retrieve the port.
* Use getPort() or getURL() after starting to retrieve the port.
* </p>
*
*
* @param args the argument list
* @param args the argument list
* @return the server
* @return the server
...
@@ -463,6 +464,7 @@ public class Server extends Tool implements Runnable, ShutdownHandler {
...
@@ -463,6 +464,7 @@ public class Server extends Tool implements Runnable, ShutdownHandler {
* If no port is specified, the default port is used if possible,
* If no port is specified, the default port is used if possible,
* and if this port is already used, a random port is used.
* and if this port is already used, a random port is used.
* Use getPort() or getURL() after starting to retrieve the port.
* Use getPort() or getURL() after starting to retrieve the port.
* </p>
*
*
* @param args the argument list
* @param args the argument list
* @return the server
* @return the server
...
...
h2/src/main/org/h2/util/DebuggingThreadLocal.java
浏览文件 @
99d6c3ee
...
@@ -9,7 +9,7 @@ import java.util.HashMap;
...
@@ -9,7 +9,7 @@ import java.util.HashMap;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
/**
* Similar to ThreadLocal, except that it allows it
'
s data to be read from other
* Similar to ThreadLocal, except that it allows its data to be read from other
* threads - useful for debugging info.
* threads - useful for debugging info.
*
*
* @param <T> the type
* @param <T> the type
...
@@ -22,6 +22,9 @@ public class DebuggingThreadLocal<T> {
...
@@ -22,6 +22,9 @@ public class DebuggingThreadLocal<T> {
map
.
put
(
Thread
.
currentThread
().
getId
(),
value
);
map
.
put
(
Thread
.
currentThread
().
getId
(),
value
);
}
}
/**
* Remove the value for the current thread.
*/
public
void
remove
()
{
public
void
remove
()
{
map
.
remove
(
Thread
.
currentThread
().
getId
());
map
.
remove
(
Thread
.
currentThread
().
getId
());
}
}
...
@@ -31,14 +34,12 @@ public class DebuggingThreadLocal<T> {
...
@@ -31,14 +34,12 @@ public class DebuggingThreadLocal<T> {
}
}
/**
/**
* Get a snapshot of the data of all threads.
*
* @return a HashMap containing a mapping from thread-id to value
* @return a HashMap containing a mapping from thread-id to value
*/
*/
public
HashMap
<
Long
,
T
>
getSnapshotOfAllThreads
()
{
public
HashMap
<
Long
,
T
>
getSnapshotOfAllThreads
()
{
return
new
HashMap
<
Long
,
T
>(
map
);
return
new
HashMap
<
Long
,
T
>(
map
);
}
}
public
T
deepCopy
(
T
value
)
{
return
value
;
}
}
}
h2/src/main/org/h2/util/ThreadDeadlockDetector.java
浏览文件 @
99d6c3ee
...
@@ -20,8 +20,8 @@ import java.util.TimerTask;
...
@@ -20,8 +20,8 @@ import java.util.TimerTask;
import
org.h2.mvstore.db.MVTable
;
import
org.h2.mvstore.db.MVTable
;
/**
/**
* Detects deadlocks between threads. Prints out data in the same format as the
CTRL-BREAK handler,
* Detects deadlocks between threads. Prints out data in the same format as the
* but includes information about table locks.
*
CTRL-BREAK handler,
but includes information about table locks.
*/
*/
public
class
ThreadDeadlockDetector
{
public
class
ThreadDeadlockDetector
{
...
@@ -29,13 +29,13 @@ public class ThreadDeadlockDetector {
...
@@ -29,13 +29,13 @@ public class ThreadDeadlockDetector {
private
static
ThreadDeadlockDetector
detector
;
private
static
ThreadDeadlockDetector
detector
;
private
final
ThreadMXBean
t
mb
ean
;
private
final
ThreadMXBean
t
hreadB
ean
;
// a daemon thread
// a daemon thread
private
final
Timer
threadCheck
=
new
Timer
(
"ThreadDeadlockDetector"
,
true
);
private
final
Timer
threadCheck
=
new
Timer
(
"ThreadDeadlockDetector"
,
true
);
private
ThreadDeadlockDetector
()
{
private
ThreadDeadlockDetector
()
{
this
.
t
mb
ean
=
ManagementFactory
.
getThreadMXBean
();
this
.
t
hreadB
ean
=
ManagementFactory
.
getThreadMXBean
();
// delay: 10 ms
// delay: 10 ms
// period: 10000 ms (100 seconds)
// period: 10000 ms (100 seconds)
threadCheck
.
schedule
(
new
TimerTask
()
{
threadCheck
.
schedule
(
new
TimerTask
()
{
...
@@ -46,6 +46,9 @@ public class ThreadDeadlockDetector {
...
@@ -46,6 +46,9 @@ public class ThreadDeadlockDetector {
},
10
,
10000
);
},
10
,
10000
);
}
}
/**
* Initialize the detector.
*/
public
static
synchronized
void
init
()
{
public
static
synchronized
void
init
()
{
if
(
detector
==
null
)
{
if
(
detector
==
null
)
{
detector
=
new
ThreadDeadlockDetector
();
detector
=
new
ThreadDeadlockDetector
();
...
@@ -53,11 +56,12 @@ public class ThreadDeadlockDetector {
...
@@ -53,11 +56,12 @@ public class ThreadDeadlockDetector {
}
}
/**
/**
* Checks if any threads are deadlocked. If any, print the thread dump information.
* Checks if any threads are deadlocked. If any, print the thread dump
* information.
*/
*/
void
checkForDeadlocks
()
{
void
checkForDeadlocks
()
{
long
[]
tids
=
tmb
ean
.
findDeadlockedThreads
();
long
[]
ids
=
threadB
ean
.
findDeadlockedThreads
();
if
(
t
ids
==
null
)
{
if
(
ids
==
null
)
{
return
;
return
;
}
}
...
@@ -65,24 +69,24 @@ public class ThreadDeadlockDetector {
...
@@ -65,24 +69,24 @@ public class ThreadDeadlockDetector {
final
PrintWriter
print
=
new
PrintWriter
(
stringWriter
);
final
PrintWriter
print
=
new
PrintWriter
(
stringWriter
);
print
.
println
(
"ThreadDeadlockDetector - deadlock found :"
);
print
.
println
(
"ThreadDeadlockDetector - deadlock found :"
);
final
ThreadInfo
[]
infos
=
t
mbean
.
getThreadInfo
(
t
ids
,
true
,
true
);
final
ThreadInfo
[]
infos
=
t
hreadBean
.
getThreadInfo
(
ids
,
true
,
true
);
final
HashMap
<
Long
,
String
>
mv
tableWaitingForLockMap
=
final
HashMap
<
Long
,
String
>
tableWaitingForLockMap
=
MVTable
.
WAITING_FOR_LOCK
.
getSnapshotOfAllThreads
();
MVTable
.
WAITING_FOR_LOCK
.
getSnapshotOfAllThreads
();
final
HashMap
<
Long
,
ArrayList
<
String
>>
mv
tableExclusiveLocksMap
=
final
HashMap
<
Long
,
ArrayList
<
String
>>
tableExclusiveLocksMap
=
MVTable
.
EXCLUSIVE_LOCKS
.
getSnapshotOfAllThreads
();
MVTable
.
EXCLUSIVE_LOCKS
.
getSnapshotOfAllThreads
();
final
HashMap
<
Long
,
ArrayList
<
String
>>
mv
tableSharedLocksMap
=
final
HashMap
<
Long
,
ArrayList
<
String
>>
tableSharedLocksMap
=
MVTable
.
SHARED_LOCKS
.
getSnapshotOfAllThreads
();
MVTable
.
SHARED_LOCKS
.
getSnapshotOfAllThreads
();
for
(
ThreadInfo
ti
:
infos
)
{
for
(
ThreadInfo
ti
:
infos
)
{
printThreadInfo
(
print
,
ti
);
printThreadInfo
(
print
,
ti
);
printLockInfo
(
print
,
ti
.
getLockedSynchronizers
(),
printLockInfo
(
print
,
ti
.
getLockedSynchronizers
(),
mv
tableWaitingForLockMap
.
get
(
ti
.
getThreadId
()),
tableWaitingForLockMap
.
get
(
ti
.
getThreadId
()),
mv
tableExclusiveLocksMap
.
get
(
ti
.
getThreadId
()),
tableExclusiveLocksMap
.
get
(
ti
.
getThreadId
()),
mv
tableSharedLocksMap
.
get
(
ti
.
getThreadId
()));
tableSharedLocksMap
.
get
(
ti
.
getThreadId
()));
}
}
print
.
flush
();
print
.
flush
();
// Dump it to system.out in one block, so it doesn't get mixed up with
other stuff when we're
// Dump it to system.out in one block, so it doesn't get mixed up with
// using a logging subsystem.
//
other stuff when we're
using a logging subsystem.
System
.
out
.
println
(
stringWriter
.
getBuffer
());
System
.
out
.
println
(
stringWriter
.
getBuffer
());
}
}
...
@@ -91,11 +95,11 @@ public class ThreadDeadlockDetector {
...
@@ -91,11 +95,11 @@ public class ThreadDeadlockDetector {
printThread
(
print
,
ti
);
printThread
(
print
,
ti
);
// print stack trace with locks
// print stack trace with locks
StackTraceElement
[]
stack
t
race
=
ti
.
getStackTrace
();
StackTraceElement
[]
stack
T
race
=
ti
.
getStackTrace
();
MonitorInfo
[]
monitors
=
ti
.
getLockedMonitors
();
MonitorInfo
[]
monitors
=
ti
.
getLockedMonitors
();
for
(
int
i
=
0
;
i
<
stack
t
race
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
stack
T
race
.
length
;
i
++)
{
StackTraceElement
ste
=
stackt
race
[
i
];
StackTraceElement
e
=
stackT
race
[
i
];
print
.
println
(
INDENT
+
"at "
+
st
e
.
toString
());
print
.
println
(
INDENT
+
"at "
+
e
.
toString
());
for
(
MonitorInfo
mi
:
monitors
)
{
for
(
MonitorInfo
mi
:
monitors
)
{
if
(
mi
.
getLockedStackDepth
()
==
i
)
{
if
(
mi
.
getLockedStackDepth
()
==
i
)
{
print
.
println
(
INDENT
+
" - locked "
+
mi
);
print
.
println
(
INDENT
+
" - locked "
+
mi
);
...
@@ -125,25 +129,25 @@ public class ThreadDeadlockDetector {
...
@@ -125,25 +129,25 @@ public class ThreadDeadlockDetector {
}
}
private
static
void
printLockInfo
(
PrintWriter
print
,
LockInfo
[]
locks
,
private
static
void
printLockInfo
(
PrintWriter
print
,
LockInfo
[]
locks
,
String
mv
tableWaitingForLock
,
String
tableWaitingForLock
,
ArrayList
<
String
>
mv
tableExclusiveLocks
,
ArrayList
<
String
>
tableExclusiveLocks
,
ArrayList
<
String
>
mv
tableSharedLocksMap
)
{
ArrayList
<
String
>
tableSharedLocksMap
)
{
print
.
println
(
INDENT
+
"Locked synchronizers: count = "
+
locks
.
length
);
print
.
println
(
INDENT
+
"Locked synchronizers: count = "
+
locks
.
length
);
for
(
LockInfo
li
:
locks
)
{
for
(
LockInfo
li
:
locks
)
{
print
.
println
(
INDENT
+
" - "
+
li
);
print
.
println
(
INDENT
+
" - "
+
li
);
}
}
if
(
mv
tableWaitingForLock
!=
null
)
{
if
(
tableWaitingForLock
!=
null
)
{
print
.
println
(
INDENT
+
"Waiting for table: "
+
mv
tableWaitingForLock
);
print
.
println
(
INDENT
+
"Waiting for table: "
+
tableWaitingForLock
);
}
}
if
(
mv
tableExclusiveLocks
!=
null
)
{
if
(
tableExclusiveLocks
!=
null
)
{
print
.
println
(
INDENT
+
"Exclusive table locks: count = "
+
mv
tableExclusiveLocks
.
size
());
print
.
println
(
INDENT
+
"Exclusive table locks: count = "
+
tableExclusiveLocks
.
size
());
for
(
String
name
:
mv
tableExclusiveLocks
)
{
for
(
String
name
:
tableExclusiveLocks
)
{
print
.
println
(
INDENT
+
" - "
+
name
);
print
.
println
(
INDENT
+
" - "
+
name
);
}
}
}
}
if
(
mv
tableSharedLocksMap
!=
null
)
{
if
(
tableSharedLocksMap
!=
null
)
{
print
.
println
(
INDENT
+
"Shared table locks: count = "
+
mv
tableSharedLocksMap
.
size
());
print
.
println
(
INDENT
+
"Shared table locks: count = "
+
tableSharedLocksMap
.
size
());
for
(
String
name
:
mv
tableSharedLocksMap
)
{
for
(
String
name
:
tableSharedLocksMap
)
{
print
.
println
(
INDENT
+
" - "
+
name
);
print
.
println
(
INDENT
+
" - "
+
name
);
}
}
}
}
...
...
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
99d6c3ee
...
@@ -1005,7 +1005,7 @@ public abstract class TestBase {
...
@@ -1005,7 +1005,7 @@ public abstract class TestBase {
/**
/**
* Check that executing the specified query results in the specified error.
* Check that executing the specified query results in the specified error.
*
*
* @param expectedError
Message the expected error messag
e
* @param expectedError
Code the expected error cod
e
* @param stat the statement
* @param stat the statement
* @param sql the SQL statement to execute
* @param sql the SQL statement to execute
*/
*/
...
...
h2/src/test/org/h2/test/db/TestCompatibilityOracle.java
浏览文件 @
99d6c3ee
...
@@ -130,8 +130,10 @@ public class TestCompatibilityOracle extends TestBase {
...
@@ -130,8 +130,10 @@ public class TestCompatibilityOracle extends TestBase {
Connection
conn
=
getConnection
(
"oracle;MODE=Oracle"
);
Connection
conn
=
getConnection
(
"oracle;MODE=Oracle"
);
Statement
stat
=
conn
.
createStatement
();
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE TEST(ID INT PRIMARY KEY, U##NAME VARCHAR(255))"
);
stat
.
execute
(
stat
.
execute
(
"INSERT INTO TEST VALUES(1, 'Hello'), (2, 'HelloWorld'), (3, 'HelloWorldWorld')"
);
"CREATE TABLE TEST(ID INT PRIMARY KEY, U##NAME VARCHAR(255))"
);
stat
.
execute
(
"INSERT INTO TEST VALUES(1, 'Hello'), (2, 'HelloWorld'), (3, 'HelloWorldWorld')"
);
assertResult
(
"1"
,
stat
,
"SELECT ID FROM TEST where U##NAME ='Hello'"
);
assertResult
(
"1"
,
stat
,
"SELECT ID FROM TEST where U##NAME ='Hello'"
);
...
...
h2/src/test/org/h2/test/db/TestFunctions.java
浏览文件 @
99d6c3ee
...
@@ -1227,7 +1227,8 @@ public class TestFunctions extends TestBase implements AggregateFunction {
...
@@ -1227,7 +1227,8 @@ public class TestFunctions extends TestBase implements AggregateFunction {
Connection
conn
=
getConnection
(
"functions"
);
Connection
conn
=
getConnection
(
"functions"
);
Statement
stat
=
conn
.
createStatement
();
Statement
stat
=
conn
.
createStatement
();
String
testStr
=
"foo"
;
String
testStr
=
"foo"
;
assertResult
(
String
.
valueOf
(
"foo"
.
hashCode
()),
stat
,
String
.
format
(
"SELECT ORA_HASH('%s') FROM DUAL"
,
testStr
));
assertResult
(
String
.
valueOf
(
"foo"
.
hashCode
()),
stat
,
String
.
format
(
"SELECT ORA_HASH('%s') FROM DUAL"
,
testStr
));
assertResult
(
String
.
valueOf
(
"foo"
.
hashCode
()),
stat
,
assertResult
(
String
.
valueOf
(
"foo"
.
hashCode
()),
stat
,
String
.
format
(
"SELECT ORA_HASH('%s', 0) FROM DUAL"
,
testStr
));
String
.
format
(
"SELECT ORA_HASH('%s', 0) FROM DUAL"
,
testStr
));
assertResult
(
String
.
valueOf
(
"foo"
.
hashCode
()),
stat
,
assertResult
(
String
.
valueOf
(
"foo"
.
hashCode
()),
stat
,
...
@@ -1327,8 +1328,6 @@ public class TestFunctions extends TestBase implements AggregateFunction {
...
@@ -1327,8 +1328,6 @@ public class TestFunctions extends TestBase implements AggregateFunction {
Timestamp
.
valueOf
(
"1979-11-12 08:12:34.560"
));
Timestamp
.
valueOf
(
"1979-11-12 08:12:34.560"
));
assertResult
(
expected
,
stat
,
assertResult
(
expected
,
stat
,
"SELECT TO_CHAR(X, 'DL') FROM T"
);
"SELECT TO_CHAR(X, 'DL') FROM T"
);
// assertResult("Monday, November 12, 1979", stat,
// "SELECT TO_CHAR(X, 'DL', 'NLS_DATE_LANGUAGE = English') FROM T");
assertResult
(
"11/12/1979"
,
stat
,
"SELECT TO_CHAR(X, 'DS') FROM T"
);
assertResult
(
"11/12/1979"
,
stat
,
"SELECT TO_CHAR(X, 'DS') FROM T"
);
assertResult
(
"11/12/1979"
,
stat
,
"SELECT TO_CHAR(X, 'Ds') FROM T"
);
assertResult
(
"11/12/1979"
,
stat
,
"SELECT TO_CHAR(X, 'Ds') FROM T"
);
assertResult
(
"11/12/1979"
,
stat
,
"SELECT TO_CHAR(X, 'dS') FROM T"
);
assertResult
(
"11/12/1979"
,
stat
,
"SELECT TO_CHAR(X, 'dS') FROM T"
);
...
...
h2/src/test/org/h2/test/poweroff/TestReorderWrites.java
浏览文件 @
99d6c3ee
...
@@ -59,7 +59,7 @@ public class TestReorderWrites extends TestBase {
...
@@ -59,7 +59,7 @@ public class TestReorderWrites extends TestBase {
store
.
commit
();
store
.
commit
();
store
.
getFileStore
().
sync
();
store
.
getFileStore
().
sync
();
int
stop
=
4
+
r
.
nextInt
(
20
);
int
stop
=
4
+
r
.
nextInt
(
20
);
log
(
"
synched
start"
);
log
(
"
countdown
start"
);
fs
.
setPowerOffCountdown
(
stop
,
i
);
fs
.
setPowerOffCountdown
(
stop
,
i
);
try
{
try
{
for
(
int
j
=
1
;
j
<
100
;
j
++)
{
for
(
int
j
=
1
;
j
<
100
;
j
++)
{
...
...
h2/src/test/org/h2/test/unit/TestValueHashMap.java
浏览文件 @
99d6c3ee
h2/src/test/org/h2/test/unit/TestValueMemory.java
浏览文件 @
99d6c3ee
h2/src/test/org/h2/test/utils/FilePathReorderWrites.java
浏览文件 @
99d6c3ee
...
@@ -25,6 +25,9 @@ import org.h2.util.IOUtils;
...
@@ -25,6 +25,9 @@ import org.h2.util.IOUtils;
*/
*/
public
class
FilePathReorderWrites
extends
FilePathWrapper
{
public
class
FilePathReorderWrites
extends
FilePathWrapper
{
/**
* Whether trace output of all method calls is enabled.
*/
static
final
boolean
TRACE
=
false
;
static
final
boolean
TRACE
=
false
;
private
static
final
FilePathReorderWrites
INSTANCE
=
new
FilePathReorderWrites
();
private
static
final
FilePathReorderWrites
INSTANCE
=
new
FilePathReorderWrites
();
...
@@ -48,8 +51,8 @@ public class FilePathReorderWrites extends FilePathWrapper {
...
@@ -48,8 +51,8 @@ public class FilePathReorderWrites extends FilePathWrapper {
}
}
/**
/**
* Set the number of write operations before a simulated power failure, and
the
* Set the number of write operations before a simulated power failure, and
* random seed (for partial writes).
*
the
random seed (for partial writes).
*
*
* @param count the number of write operations (0 to never fail,
* @param count the number of write operations (0 to never fail,
* Integer.MAX_VALUE to count the operations)
* Integer.MAX_VALUE to count the operations)
...
@@ -150,7 +153,8 @@ class FileReorderWrites extends FileBase {
...
@@ -150,7 +153,8 @@ class FileReorderWrites extends FileBase {
private
final
FileChannel
base
;
private
final
FileChannel
base
;
/**
/**
* The base channel that is used for reading, where all operations are immediately applied to get a consistent view before a power failure.
* The base channel that is used for reading, where all operations are
* immediately applied to get a consistent view before a power failure.
*/
*/
private
final
FileChannel
readBase
;
private
final
FileChannel
readBase
;
...
@@ -216,12 +220,12 @@ class FileReorderWrites extends FileBase {
...
@@ -216,12 +220,12 @@ class FileReorderWrites extends FileBase {
trace
(
"op "
+
op
);
trace
(
"op "
+
op
);
checkError
();
checkError
();
notAppliedList
.
add
(
op
);
notAppliedList
.
add
(
op
);
long
now
=
op
.
time
;
long
now
=
op
.
getTime
()
;
for
(
int
i
=
0
;
i
<
notAppliedList
.
size
()
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
notAppliedList
.
size
()
-
1
;
i
++)
{
FileOperation
old
=
notAppliedList
.
get
(
i
);
FileOperation
old
=
notAppliedList
.
get
(
i
);
boolean
applyOld
=
false
;
boolean
applyOld
=
false
;
// String reason = "";
// String reason = "";
if
(
old
.
time
+
45000
<
now
)
{
if
(
old
.
getTime
()
+
45000
<
now
)
{
// reason = "old";
// reason = "old";
applyOld
=
true
;
applyOld
=
true
;
}
else
if
(
old
.
overlaps
(
op
))
{
}
else
if
(
old
.
overlaps
(
op
))
{
...
@@ -295,10 +299,10 @@ class FileReorderWrites extends FileBase {
...
@@ -295,10 +299,10 @@ class FileReorderWrites extends FileBase {
* be applied on power failure).
* be applied on power failure).
*/
*/
static
class
FileOperation
{
static
class
FileOperation
{
final
int
id
;
private
final
int
id
;
final
long
time
;
private
final
long
time
;
final
ByteBuffer
buffer
;
private
final
ByteBuffer
buffer
;
final
long
position
;
private
final
long
position
;
FileOperation
(
int
id
,
long
position
,
ByteBuffer
src
)
{
FileOperation
(
int
id
,
long
position
,
ByteBuffer
src
)
{
this
.
id
=
id
;
this
.
id
=
id
;
...
@@ -314,7 +318,18 @@ class FileReorderWrites extends FileBase {
...
@@ -314,7 +318,18 @@ class FileReorderWrites extends FileBase {
this
.
position
=
position
;
this
.
position
=
position
;
}
}
public
boolean
overlaps
(
FileOperation
other
)
{
public
long
getTime
()
{
return
time
;
}
/**
* Check whether the file region of this operation overlaps with
* another operation.
*
* @param other the other operation
* @return if there is an overlap
*/
boolean
overlaps
(
FileOperation
other
)
{
if
(
isTruncate
()
&&
other
.
isTruncate
())
{
if
(
isTruncate
()
&&
other
.
isTruncate
())
{
// we just keep the latest truncate operation
// we just keep the latest truncate operation
return
true
;
return
true
;
...
@@ -340,6 +355,12 @@ class FileReorderWrites extends FileBase {
...
@@ -340,6 +355,12 @@ class FileReorderWrites extends FileBase {
return
buffer
==
null
?
0
:
buffer
.
limit
()
-
buffer
.
position
();
return
buffer
==
null
?
0
:
buffer
.
limit
()
-
buffer
.
position
();
}
}
/**
* Apply the operation to the channel.
*
* @param channel the channel
* @return the return value of the operation
*/
int
apply
(
FileChannel
channel
)
throws
IOException
{
int
apply
(
FileChannel
channel
)
throws
IOException
{
if
(
isTruncate
())
{
if
(
isTruncate
())
{
channel
.
truncate
(
position
);
channel
.
truncate
(
position
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论