Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
f1ecb149
Unverified
提交
f1ecb149
authored
7 年前
作者:
Noel Grandin
提交者:
GitHub
7 年前
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #867 from h2database/test_out_of_memory
TestOutOfMemory stability
上级
c812500b
001fd181
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
245 行增加
和
183 行删除
+245
-183
Database.java
h2/src/main/org/h2/engine/Database.java
+92
-88
DatabaseCloser.java
h2/src/main/org/h2/engine/DatabaseCloser.java
+2
-1
Engine.java
h2/src/main/org/h2/engine/Engine.java
+29
-24
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+1
-1
JdbcPreparedStatement.java
h2/src/main/org/h2/jdbc/JdbcPreparedStatement.java
+1
-1
DbException.java
h2/src/main/org/h2/message/DbException.java
+1
-1
TraceObject.java
h2/src/main/org/h2/message/TraceObject.java
+17
-9
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+18
-16
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+8
-1
TestOutOfMemory.java
h2/src/test/org/h2/test/db/TestOutOfMemory.java
+76
-41
没有找到文件。
h2/src/main/org/h2/engine/Database.java
浏览文件 @
f1ecb149
...
@@ -209,6 +209,8 @@ public class Database implements DataHandler {
...
@@ -209,6 +209,8 @@ public class Database implements DataHandler {
private
RowFactory
rowFactory
=
RowFactory
.
DEFAULT
;
private
RowFactory
rowFactory
=
RowFactory
.
DEFAULT
;
public
Database
(
ConnectionInfo
ci
,
String
cipher
)
{
public
Database
(
ConnectionInfo
ci
,
String
cipher
)
{
META_LOCK_DEBUGGING
.
set
(
null
);
META_LOCK_DEBUGGING_STACK
.
set
(
null
);
String
name
=
ci
.
getName
();
String
name
=
ci
.
getName
();
this
.
dbSettings
=
ci
.
getDbSettings
();
this
.
dbSettings
=
ci
.
getDbSettings
();
this
.
reconnectCheckDelayNs
=
TimeUnit
.
MILLISECONDS
.
toNanos
(
dbSettings
.
reconnectCheckDelay
);
this
.
reconnectCheckDelayNs
=
TimeUnit
.
MILLISECONDS
.
toNanos
(
dbSettings
.
reconnectCheckDelay
);
...
@@ -1256,110 +1258,112 @@ public class Database implements DataHandler {
...
@@ -1256,110 +1258,112 @@ public class Database implements DataHandler {
* hook
* hook
*/
*/
void
close
(
boolean
fromShutdownHook
)
{
void
close
(
boolean
fromShutdownHook
)
{
synchronized
(
this
)
{
try
{
if
(
closing
)
{
synchronized
(
this
)
{
return
;
if
(
closing
)
{
}
throwLastBackgroundException
();
if
(
fileLockMethod
==
FileLockMethod
.
SERIALIZED
&&
!
reconnectChangePending
)
{
// another connection may have written something - don't write
try
{
closeOpenFilesAndUnlock
(
false
);
}
catch
(
DbException
e
)
{
// ignore
}
traceSystem
.
close
();
Engine
.
getInstance
().
close
(
databaseName
);
return
;
}
closing
=
true
;
stopServer
();
if
(!
userSessions
.
isEmpty
())
{
if
(!
fromShutdownHook
)
{
return
;
return
;
}
}
trace
.
info
(
"closing {0} from shutdown hook"
,
databaseName
);
throwLastBackgroundException
();
closeAllSessionsException
(
null
);
if
(
fileLockMethod
==
FileLockMethod
.
SERIALIZED
&&
}
!
reconnectChangePending
)
{
trace
.
info
(
"closing {0}"
,
databaseName
);
// another connection may have written something - don't write
if
(
eventListener
!=
null
)
{
try
{
// allow the event listener to connect to the database
closeOpenFilesAndUnlock
(
false
);
closing
=
false
;
}
catch
(
DbException
e
)
{
DatabaseEventListener
e
=
eventListener
;
// ignore
// set it to null, to make sure it's called only once
}
eventListener
=
null
;
traceSystem
.
close
();
e
.
closingDatabase
();
if
(!
userSessions
.
isEmpty
())
{
// if a connection was opened, we can't close the database
return
;
return
;
}
}
closing
=
true
;
closing
=
true
;
stopServer
();
if
(!
userSessions
.
isEmpty
())
{
if
(!
fromShutdownHook
)
{
return
;
}
trace
.
info
(
"closing {0} from shutdown hook"
,
databaseName
);
closeAllSessionsException
(
null
);
}
trace
.
info
(
"closing {0}"
,
databaseName
);
if
(
eventListener
!=
null
)
{
// allow the event listener to connect to the database
closing
=
false
;
DatabaseEventListener
e
=
eventListener
;
// set it to null, to make sure it's called only once
eventListener
=
null
;
e
.
closingDatabase
();
if
(!
userSessions
.
isEmpty
())
{
// if a connection was opened, we can't close the database
return
;
}
closing
=
true
;
}
}
}
}
removeOrphanedLobs
();
removeOrphanedLobs
();
try
{
try
{
if
(
systemSession
!=
null
)
{
if
(
systemSession
!=
null
)
{
if
(
powerOffCount
!=
-
1
)
{
if
(
powerOffCount
!=
-
1
)
{
for
(
Table
table
:
getAllTablesAndViews
(
false
))
{
for
(
Table
table
:
getAllTablesAndViews
(
false
))
{
if
(
table
.
isGlobalTemporary
())
{
if
(
table
.
isGlobalTemporary
())
{
table
.
removeChildrenAndResources
(
systemSession
);
table
.
removeChildrenAndResources
(
systemSession
);
}
else
{
}
else
{
table
.
close
(
systemSession
);
table
.
close
(
systemSession
);
}
}
for
(
SchemaObject
obj
:
getAllSchemaObjects
(
DbObject
.
SEQUENCE
))
{
Sequence
sequence
=
(
Sequence
)
obj
;
sequence
.
close
();
}
}
}
}
for
(
SchemaObject
obj
:
getAllSchemaObjects
(
for
(
SchemaObject
obj
:
getAllSchemaObjects
(
DbObject
.
SEQUENCE
))
{
DbObject
.
TRIGGER
))
{
Sequence
sequence
=
(
Sequence
)
obj
;
TriggerObject
trigger
=
(
TriggerObject
)
obj
;
sequence
.
close
();
try
{
trigger
.
close
();
}
catch
(
SQLException
e
)
{
trace
.
error
(
e
,
"close"
);
}
}
}
}
if
(
powerOffCount
!=
-
1
)
{
for
(
SchemaObject
obj
:
getAllSchemaObjects
(
meta
.
close
(
systemSession
);
DbObject
.
TRIGGER
))
{
systemSession
.
commit
(
true
);
TriggerObject
trigger
=
(
TriggerObject
)
obj
;
try
{
trigger
.
close
();
}
catch
(
SQLException
e
)
{
trace
.
error
(
e
,
"close"
);
}
}
}
}
if
(
powerOffCount
!=
-
1
)
{
}
catch
(
DbException
e
)
{
meta
.
close
(
systemSession
);
trace
.
error
(
e
,
"close"
);
systemSession
.
commit
(
true
);
}
}
}
}
catch
(
DbException
e
)
{
tempFileDeleter
.
deleteAll
();
trace
.
error
(
e
,
"close"
);
}
tempFileDeleter
.
deleteAll
();
try
{
closeOpenFilesAndUnlock
(
true
);
}
catch
(
DbException
e
)
{
trace
.
error
(
e
,
"close"
);
}
trace
.
info
(
"closed"
);
traceSystem
.
close
();
if
(
closeOnExit
!=
null
)
{
closeOnExit
.
reset
();
try
{
try
{
Runtime
.
getRuntime
().
removeShutdownHook
(
closeOnExit
);
closeOpenFilesAndUnlock
(
true
);
}
catch
(
IllegalStateException
e
)
{
}
catch
(
DbException
e
)
{
// ignore
trace
.
error
(
e
,
"close"
);
}
catch
(
SecurityException
e
)
{
// applets may not do that - ignore
}
}
closeOnExit
=
null
;
trace
.
info
(
"closed"
);
}
traceSystem
.
close
();
Engine
.
getInstance
().
close
(
databaseName
);
if
(
closeOnExit
!=
null
)
{
if
(
deleteFilesOnDisconnect
&&
persistent
)
{
closeOnExit
.
reset
();
deleteFilesOnDisconnect
=
false
;
try
{
try
{
Runtime
.
getRuntime
().
removeShutdownHook
(
closeOnExit
);
String
directory
=
FileUtils
.
getParent
(
databaseName
);
}
catch
(
IllegalStateException
e
)
{
String
name
=
FileUtils
.
getName
(
databaseName
);
// ignore
DeleteDbFiles
.
execute
(
directory
,
name
,
true
);
}
catch
(
SecurityException
e
)
{
}
catch
(
Exception
e
)
{
// applets may not do that - ignore
// ignore (the trace is closed already)
}
closeOnExit
=
null
;
}
if
(
deleteFilesOnDisconnect
&&
persistent
)
{
deleteFilesOnDisconnect
=
false
;
try
{
String
directory
=
FileUtils
.
getParent
(
databaseName
);
String
name
=
FileUtils
.
getName
(
databaseName
);
DeleteDbFiles
.
execute
(
directory
,
name
,
true
);
}
catch
(
Exception
e
)
{
// ignore (the trace is closed already)
}
}
}
}
finally
{
Engine
.
getInstance
().
close
(
databaseName
);
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/DatabaseCloser.java
浏览文件 @
f1ecb149
...
@@ -69,7 +69,8 @@ class DatabaseCloser extends Thread {
...
@@ -69,7 +69,8 @@ class DatabaseCloser extends Thread {
trace
.
error
(
e
,
"could not close the database"
);
trace
.
error
(
e
,
"could not close the database"
);
// if this was successful, we ignore the exception
// if this was successful, we ignore the exception
// otherwise not
// otherwise not
}
catch
(
RuntimeException
e2
)
{
}
catch
(
Throwable
e2
)
{
e
.
addSuppressed
(
e2
);
throw
e
;
throw
e
;
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/Engine.java
浏览文件 @
f1ecb149
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
package
org
.
h2
.
engine
;
package
org
.
h2
.
engine
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Objects
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.CommandInterface
;
...
@@ -27,7 +28,7 @@ import org.h2.util.Utils;
...
@@ -27,7 +28,7 @@ import org.h2.util.Utils;
public
class
Engine
implements
SessionFactory
{
public
class
Engine
implements
SessionFactory
{
private
static
final
Engine
INSTANCE
=
new
Engine
();
private
static
final
Engine
INSTANCE
=
new
Engine
();
private
static
final
Hash
Map
<
String
,
Database
>
DATABASES
=
new
HashMap
<>();
private
static
final
Map
<
String
,
Database
>
DATABASES
=
new
HashMap
<>();
private
volatile
long
wrongPasswordDelay
=
private
volatile
long
wrongPasswordDelay
=
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
...
@@ -50,30 +51,32 @@ public class Engine implements SessionFactory {
...
@@ -50,30 +51,32 @@ public class Engine implements SessionFactory {
Database
database
;
Database
database
;
ci
.
removeProperty
(
"NO_UPGRADE"
,
false
);
ci
.
removeProperty
(
"NO_UPGRADE"
,
false
);
boolean
openNew
=
ci
.
getProperty
(
"OPEN_NEW"
,
false
);
boolean
openNew
=
ci
.
getProperty
(
"OPEN_NEW"
,
false
);
if
(
openNew
||
ci
.
isUnnamedInMemory
())
{
database
=
null
;
}
else
{
database
=
DATABASES
.
get
(
name
);
}
User
user
=
null
;
boolean
opened
=
false
;
boolean
opened
=
false
;
if
(
database
==
null
)
{
User
user
=
null
;
if
(
ifExists
&&
!
Database
.
exists
(
name
))
{
synchronized
(
DATABASES
)
{
throw
DbException
.
get
(
ErrorCode
.
DATABASE_NOT_FOUND_1
,
name
);
if
(
openNew
||
ci
.
isUnnamedInMemory
())
{
}
database
=
null
;
database
=
new
Database
(
ci
,
cipher
);
}
else
{
opened
=
true
;
database
=
DATABASES
.
get
(
name
);
if
(
database
.
getAllUsers
().
isEmpty
())
{
// users is the last thing we add, so if no user is around,
// the database is new (or not initialized correctly)
user
=
new
User
(
database
,
database
.
allocateObjectId
(),
ci
.
getUserName
(),
false
);
user
.
setAdmin
(
true
);
user
.
setUserPasswordHash
(
ci
.
getUserPasswordHash
());
database
.
setMasterUser
(
user
);
}
}
if
(!
ci
.
isUnnamedInMemory
())
{
if
(
database
==
null
)
{
DATABASES
.
put
(
name
,
database
);
if
(
ifExists
&&
!
Database
.
exists
(
name
))
{
throw
DbException
.
get
(
ErrorCode
.
DATABASE_NOT_FOUND_1
,
name
);
}
database
=
new
Database
(
ci
,
cipher
);
opened
=
true
;
if
(
database
.
getAllUsers
().
isEmpty
())
{
// users is the last thing we add, so if no user is around,
// the database is new (or not initialized correctly)
user
=
new
User
(
database
,
database
.
allocateObjectId
(),
ci
.
getUserName
(),
false
);
user
.
setAdmin
(
true
);
user
.
setUserPasswordHash
(
ci
.
getUserPasswordHash
());
database
.
setMasterUser
(
user
);
}
if
(!
ci
.
isUnnamedInMemory
())
{
DATABASES
.
put
(
name
,
database
);
}
}
}
}
}
if
(
opened
)
{
if
(
opened
)
{
...
@@ -272,7 +275,9 @@ public class Engine implements SessionFactory {
...
@@ -272,7 +275,9 @@ public class Engine implements SessionFactory {
throw
DbException
.
get
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
e
,
"JMX"
);
throw
DbException
.
get
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
e
,
"JMX"
);
}
}
}
}
DATABASES
.
remove
(
name
);
synchronized
(
DATABASES
)
{
DATABASES
.
remove
(
name
);
}
}
}
/**
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
f1ecb149
...
@@ -411,7 +411,7 @@ public class JdbcConnection extends TraceObject
...
@@ -411,7 +411,7 @@ public class JdbcConnection extends TraceObject
session
=
null
;
session
=
null
;
}
}
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Throwable
e
)
{
throw
logAndConvert
(
e
);
throw
logAndConvert
(
e
);
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/jdbc/JdbcPreparedStatement.java
浏览文件 @
f1ecb149
...
@@ -248,7 +248,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements
...
@@ -248,7 +248,7 @@ public class JdbcPreparedStatement extends JdbcStatement implements
}
finally
{
}
finally
{
afterWriting
();
afterWriting
();
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Throwable
e
)
{
throw
logAndConvert
(
e
);
throw
logAndConvert
(
e
);
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/message/DbException.java
浏览文件 @
f1ecb149
...
@@ -273,7 +273,7 @@ public class DbException extends RuntimeException {
...
@@ -273,7 +273,7 @@ public class DbException extends RuntimeException {
* @param e the root cause
* @param e the root cause
* @return the SQL exception object
* @return the SQL exception object
*/
*/
public
static
SQLException
toSQLException
(
Exception
e
)
{
public
static
SQLException
toSQLException
(
Throwable
e
)
{
if
(
e
instanceof
SQLException
)
{
if
(
e
instanceof
SQLException
)
{
return
(
SQLException
)
e
;
return
(
SQLException
)
e
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/message/TraceObject.java
浏览文件 @
f1ecb149
...
@@ -351,17 +351,25 @@ public class TraceObject {
...
@@ -351,17 +351,25 @@ public class TraceObject {
* @param ex the exception
* @param ex the exception
* @return the SQL exception object
* @return the SQL exception object
*/
*/
protected
SQLException
logAndConvert
(
Exception
ex
)
{
protected
SQLException
logAndConvert
(
Throwable
ex
)
{
SQLException
e
=
DbException
.
toSQLException
(
ex
);
SQLException
e
=
null
;
if
(
trace
==
null
)
{
try
{
DbException
.
traceThrowable
(
e
);
e
=
DbException
.
toSQLException
(
ex
);
}
else
{
if
(
trace
==
null
)
{
int
errorCode
=
e
.
getErrorCode
();
DbException
.
traceThrowable
(
e
);
if
(
errorCode
>=
23000
&&
errorCode
<
24000
)
{
trace
.
info
(
e
,
"exception"
);
}
else
{
}
else
{
trace
.
error
(
e
,
"exception"
);
int
errorCode
=
e
.
getErrorCode
();
if
(
errorCode
>=
23000
&&
errorCode
<
24000
)
{
trace
.
info
(
e
,
"exception"
);
}
else
{
trace
.
error
(
e
,
"exception"
);
}
}
}
catch
(
Throwable
ignore
)
{
if
(
e
==
null
)
{
e
=
new
SQLException
(
""
,
"HY000"
,
ex
);
}
}
e
.
addSuppressed
(
ignore
);
}
}
return
e
;
return
e
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
f1ecb149
...
@@ -380,9 +380,7 @@ public final class MVStore {
...
@@ -380,9 +380,7 @@ public final class MVStore {
}
}
private
void
panic
(
IllegalStateException
e
)
{
private
void
panic
(
IllegalStateException
e
)
{
if
(
backgroundExceptionHandler
!=
null
)
{
handleException
(
e
);
backgroundExceptionHandler
.
uncaughtException
(
null
,
e
);
}
panicException
=
e
;
panicException
=
e
;
closeImmediately
();
closeImmediately
();
throw
e
;
throw
e
;
...
@@ -862,10 +860,8 @@ public final class MVStore {
...
@@ -862,10 +860,8 @@ public final class MVStore {
public
void
closeImmediately
()
{
public
void
closeImmediately
()
{
try
{
try
{
closeStore
(
false
);
closeStore
(
false
);
}
catch
(
Exception
e
)
{
}
catch
(
Throwable
e
)
{
if
(
backgroundExceptionHandler
!=
null
)
{
handleException
(
e
);
backgroundExceptionHandler
.
uncaughtException
(
null
,
e
);
}
}
}
}
}
...
@@ -2468,11 +2464,9 @@ public final class MVStore {
...
@@ -2468,11 +2464,9 @@ public final class MVStore {
if
(
hasUnsavedChanges
())
{
if
(
hasUnsavedChanges
())
{
try
{
try
{
commitAndSave
();
commitAndSave
();
}
catch
(
Exception
e
)
{
}
catch
(
Throwable
e
)
{
if
(
backgroundExceptionHandler
!=
null
)
{
handleException
(
e
);
backgroundExceptionHandler
.
uncaughtException
(
null
,
e
);
return
;
return
;
}
}
}
}
}
if
(
autoCompactFillRate
>
0
)
{
if
(
autoCompactFillRate
>
0
)
{
...
@@ -2492,10 +2486,18 @@ public final class MVStore {
...
@@ -2492,10 +2486,18 @@ public final class MVStore {
// in the bookkeeping?
// in the bookkeeping?
compact
(
fillRate
,
autoCommitMemory
);
compact
(
fillRate
,
autoCommitMemory
);
autoCompactLastFileOpCount
=
fileStore
.
getWriteCount
()
+
fileStore
.
getReadCount
();
autoCompactLastFileOpCount
=
fileStore
.
getWriteCount
()
+
fileStore
.
getReadCount
();
}
catch
(
Exception
e
)
{
}
catch
(
Throwable
e
)
{
if
(
backgroundExceptionHandler
!=
null
)
{
handleException
(
e
);
backgroundExceptionHandler
.
uncaughtException
(
null
,
e
);
}
}
}
}
private
void
handleException
(
Throwable
ex
)
{
if
(
backgroundExceptionHandler
!=
null
)
{
try
{
backgroundExceptionHandler
.
uncaughtException
(
null
,
ex
);
}
catch
(
Throwable
ignore
)
{
ex
.
addSuppressed
(
ignore
);
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
f1ecb149
...
@@ -79,6 +79,8 @@ public abstract class TestBase {
...
@@ -79,6 +79,8 @@ public abstract class TestBase {
private
final
LinkedList
<
byte
[]>
memory
=
new
LinkedList
<>();
private
final
LinkedList
<
byte
[]>
memory
=
new
LinkedList
<>();
private
static
final
SimpleDateFormat
dateFormat
=
new
SimpleDateFormat
(
"HH:mm:ss"
);
/**
/**
* Get the test directory for this test.
* Get the test directory for this test.
*
*
...
@@ -545,7 +547,6 @@ public abstract class TestBase {
...
@@ -545,7 +547,6 @@ public abstract class TestBase {
* @param s the message
* @param s the message
*/
*/
static
synchronized
void
printlnWithTime
(
long
millis
,
String
s
)
{
static
synchronized
void
printlnWithTime
(
long
millis
,
String
s
)
{
SimpleDateFormat
dateFormat
=
new
SimpleDateFormat
(
"HH:mm:ss"
);
s
=
dateFormat
.
format
(
new
java
.
util
.
Date
())
+
" "
+
s
=
dateFormat
.
format
(
new
java
.
util
.
Date
())
+
" "
+
formatTime
(
millis
)
+
" "
+
s
;
formatTime
(
millis
)
+
" "
+
s
;
System
.
out
.
println
(
s
);
System
.
out
.
println
(
s
);
...
@@ -1470,6 +1471,12 @@ public abstract class TestBase {
...
@@ -1470,6 +1471,12 @@ public abstract class TestBase {
*/
*/
protected
void
freeMemory
()
{
protected
void
freeMemory
()
{
memory
.
clear
();
memory
.
clear
();
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
System
.
gc
();
try
{
Thread
.
sleep
(
20
);
}
catch
(
InterruptedException
ignore
)
{
/**/
}
}
}
}
/**
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestOutOfMemory.java
浏览文件 @
f1ecb149
...
@@ -13,7 +13,9 @@ import java.sql.SQLException;
...
@@ -13,7 +13,9 @@ import java.sql.SQLException;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Random
;
import
java.util.Random
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.MVStore
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePathMem
;
import
org.h2.store.fs.FilePathMem
;
...
@@ -37,10 +39,6 @@ public class TestOutOfMemory extends TestBase {
...
@@ -37,10 +39,6 @@ public class TestOutOfMemory extends TestBase {
@Override
@Override
public
void
test
()
throws
SQLException
,
InterruptedException
{
public
void
test
()
throws
SQLException
,
InterruptedException
{
if
(
config
.
travis
)
{
// fails regularly under Travis, not sure why
return
;
}
if
(
config
.
vmlens
)
{
if
(
config
.
vmlens
)
{
// running out of memory will cause the vmlens agent to stop working
// running out of memory will cause the vmlens agent to stop working
return
;
return
;
...
@@ -60,7 +58,16 @@ public class TestOutOfMemory extends TestBase {
...
@@ -60,7 +58,16 @@ public class TestOutOfMemory extends TestBase {
private
void
testMVStoreUsingInMemoryFileSystem
()
{
private
void
testMVStoreUsingInMemoryFileSystem
()
{
FilePath
.
register
(
new
FilePathMem
());
FilePath
.
register
(
new
FilePathMem
());
String
fileName
=
"memFS:"
+
getTestName
();
String
fileName
=
"memFS:"
+
getTestName
();
MVStore
store
=
MVStore
.
open
(
fileName
);
final
AtomicReference
<
Throwable
>
exRef
=
new
AtomicReference
<>();
MVStore
store
=
new
MVStore
.
Builder
()
.
fileName
(
fileName
)
.
backgroundExceptionHandler
(
new
Thread
.
UncaughtExceptionHandler
()
{
@Override
public
void
uncaughtException
(
Thread
t
,
Throwable
e
)
{
exRef
.
compareAndSet
(
null
,
e
);
}
})
.
open
();
try
{
try
{
Map
<
Integer
,
byte
[]>
map
=
store
.
openMap
(
"test"
);
Map
<
Integer
,
byte
[]>
map
=
store
.
openMap
(
"test"
);
Random
r
=
new
Random
(
1
);
Random
r
=
new
Random
(
1
);
...
@@ -70,10 +77,11 @@ public class TestOutOfMemory extends TestBase {
...
@@ -70,10 +77,11 @@ public class TestOutOfMemory extends TestBase {
r
.
nextBytes
(
data
);
r
.
nextBytes
(
data
);
map
.
put
(
i
,
data
);
map
.
put
(
i
,
data
);
}
}
Throwable
throwable
=
exRef
.
get
();
if
(
throwable
instanceof
OutOfMemoryError
)
throw
(
OutOfMemoryError
)
throwable
;
if
(
throwable
instanceof
IllegalStateException
)
throw
(
IllegalStateException
)
throwable
;
fail
();
fail
();
}
catch
(
OutOfMemoryError
e
)
{
}
catch
(
OutOfMemoryError
|
IllegalStateException
e
)
{
// expected
}
catch
(
IllegalStateException
e
)
{
// expected
// expected
}
}
try
{
try
{
...
@@ -83,7 +91,7 @@ public class TestOutOfMemory extends TestBase {
...
@@ -83,7 +91,7 @@ public class TestOutOfMemory extends TestBase {
}
}
store
.
closeImmediately
();
store
.
closeImmediately
();
store
=
MVStore
.
open
(
fileName
);
store
=
MVStore
.
open
(
fileName
);
map
=
store
.
openMap
(
"test"
);
store
.
openMap
(
"test"
);
store
.
close
();
store
.
close
();
}
finally
{
}
finally
{
// just in case, otherwise if this test suffers a spurious failure,
// just in case, otherwise if this test suffers a spurious failure,
...
@@ -95,47 +103,55 @@ public class TestOutOfMemory extends TestBase {
...
@@ -95,47 +103,55 @@ public class TestOutOfMemory extends TestBase {
private
void
testDatabaseUsingInMemoryFileSystem
()
throws
SQLException
,
InterruptedException
{
private
void
testDatabaseUsingInMemoryFileSystem
()
throws
SQLException
,
InterruptedException
{
String
filename
=
"memFS:"
+
getTestName
();
String
filename
=
"memFS:"
+
getTestName
();
String
url
=
"jdbc:h2:"
+
filename
;
String
url
=
"jdbc:h2:"
+
filename
+
"/test"
;
Connection
conn
=
DriverManager
.
getConnection
(
url
);
Statement
stat
=
conn
.
createStatement
();
try
{
stat
.
execute
(
"create table test(id int, name varchar) as "
+
"select x, space(10000000) from system_range(1, 1000)"
);
fail
();
}
catch
(
SQLException
e
)
{
int
err
=
e
.
getErrorCode
();
assertTrue
(
e
.
getMessage
(),
err
==
ErrorCode
.
GENERAL_ERROR_1
||
err
==
ErrorCode
.
OUT_OF_MEMORY
);
}
try
{
try
{
Connection
conn
=
DriverManager
.
getConnection
(
url
);
Statement
stat
=
conn
.
createStatement
();
try
{
stat
.
execute
(
"create table test(id int, name varchar) as "
+
"select x, space(10000000+x) from system_range(1, 1000)"
);
fail
();
}
catch
(
SQLException
e
)
{
assertTrue
(
"Unexpected error code: "
+
e
.
getErrorCode
(),
ErrorCode
.
OUT_OF_MEMORY
==
e
.
getErrorCode
()
||
ErrorCode
.
FILE_CORRUPTED_1
==
e
.
getErrorCode
()
||
ErrorCode
.
DATABASE_IS_CLOSED
==
e
.
getErrorCode
()
||
ErrorCode
.
GENERAL_ERROR_1
==
e
.
getErrorCode
());
}
recoverAfterOOM
();
try
{
conn
.
close
();
fail
();
}
catch
(
SQLException
e
)
{
assertTrue
(
"Unexpected error code: "
+
e
.
getErrorCode
(),
ErrorCode
.
OUT_OF_MEMORY
==
e
.
getErrorCode
()
||
ErrorCode
.
FILE_CORRUPTED_1
==
e
.
getErrorCode
()
||
ErrorCode
.
DATABASE_IS_CLOSED
==
e
.
getErrorCode
()
||
ErrorCode
.
GENERAL_ERROR_1
==
e
.
getErrorCode
());
}
recoverAfterOOM
();
conn
=
DriverManager
.
getConnection
(
url
);
stat
=
conn
.
createStatement
();
stat
.
execute
(
"SELECT 1"
);
conn
.
close
();
conn
.
close
();
fail
();
}
finally
{
}
catch
(
SQLException
e
)
{
// release the static data this test generates
int
err
=
e
.
getErrorCode
();
FileUtils
.
deleteRecursive
(
filename
,
true
);
assertTrue
(
e
.
getMessage
(),
err
==
ErrorCode
.
GENERAL_ERROR_1
||
err
==
ErrorCode
.
OUT_OF_MEMORY
||
err
==
ErrorCode
.
DATABASE_IS_CLOSED
);
}
}
}
private
static
void
recoverAfterOOM
()
throws
InterruptedException
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
System
.
gc
();
System
.
gc
();
Thread
.
sleep
(
20
);
Thread
.
sleep
(
20
);
}
}
conn
=
DriverManager
.
getConnection
(
url
);
stat
=
conn
.
createStatement
();
stat
.
execute
(
"select 1"
);
conn
.
close
();
// release the static data this test generates
FileUtils
.
delete
(
filename
);
}
}
private
void
testUpdateWhenNearlyOutOfMemory
()
throws
SQLException
,
InterruptedException
{
private
void
testUpdateWhenNearlyOutOfMemory
()
throws
SQLException
,
InterruptedException
{
if
(
config
.
memory
||
config
.
mvcc
||
config
.
mvStore
)
{
if
(
config
.
memory
)
{
return
;
return
;
}
}
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
recoverAfterOOM
();
System
.
gc
();
Thread
.
sleep
(
20
);
}
deleteDb
(
"outOfMemory"
);
deleteDb
(
"outOfMemory"
);
Connection
conn
=
getConnection
(
"outOfMemory;MAX_OPERATION_MEMORY=1000000"
);
Connection
conn
=
getConnection
(
"outOfMemory;MAX_OPERATION_MEMORY=1000000"
);
Statement
stat
=
conn
.
createStatement
();
Statement
stat
=
conn
.
createStatement
();
...
@@ -148,8 +164,27 @@ public class TestOutOfMemory extends TestBase {
...
@@ -148,8 +164,27 @@ public class TestOutOfMemory extends TestBase {
stat
.
execute
(
"checkpoint"
);
stat
.
execute
(
"checkpoint"
);
eatMemory
(
80
);
eatMemory
(
80
);
try
{
try
{
assertThrows
(
ErrorCode
.
OUT_OF_MEMORY
,
prep
).
execute
();
try
{
assertThrows
(
ErrorCode
.
DATABASE_IS_CLOSED
,
conn
).
close
();
prep
.
execute
();
fail
();
}
catch
(
DbException
ex
)
{
freeMemory
();
assertTrue
(
ErrorCode
.
OUT_OF_MEMORY
==
ex
.
getErrorCode
()
||
ErrorCode
.
GENERAL_ERROR_1
==
ex
.
getErrorCode
());
}
catch
(
SQLException
ex
)
{
freeMemory
();
assertTrue
(
ErrorCode
.
OUT_OF_MEMORY
==
ex
.
getErrorCode
()
||
ErrorCode
.
GENERAL_ERROR_1
==
ex
.
getErrorCode
());
}
recoverAfterOOM
();
try
{
conn
.
close
();
fail
();
}
catch
(
DbException
ex
)
{
freeMemory
();
assertEquals
(
ErrorCode
.
DATABASE_IS_CLOSED
,
ex
.
getErrorCode
());
}
catch
(
SQLException
ex
)
{
freeMemory
();
assertEquals
(
ErrorCode
.
DATABASE_IS_CLOSED
,
ex
.
getErrorCode
());
}
freeMemory
();
freeMemory
();
conn
=
null
;
conn
=
null
;
conn
=
getConnection
(
"outOfMemory"
);
conn
=
getConnection
(
"outOfMemory"
);
...
@@ -160,7 +195,7 @@ public class TestOutOfMemory extends TestBase {
...
@@ -160,7 +195,7 @@ public class TestOutOfMemory extends TestBase {
}
catch
(
OutOfMemoryError
e
)
{
}
catch
(
OutOfMemoryError
e
)
{
freeMemory
();
freeMemory
();
// out of memory not detected
// out of memory not detected
throw
(
Error
)
new
AssertionError
(
"Out of memory not detected"
).
initCause
(
e
);
throw
new
AssertionError
(
"Out of memory not detected"
,
e
);
}
finally
{
}
finally
{
freeMemory
();
freeMemory
();
if
(
conn
!=
null
)
{
if
(
conn
!=
null
)
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论