Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
f3ec805a
提交
f3ec805a
authored
8 年前
作者:
Noel Grandin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Issue #324: Deadlock when sending BLOBs over TCP
上级
add3db91
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
58 行增加
和
50 行删除
+58
-50
changelog.html
h2/src/docsrc/html/changelog.html
+2
-0
Function.java
h2/src/main/org/h2/expression/Function.java
+3
-2
CountingReaderInputStream.java
h2/src/main/org/h2/store/CountingReaderInputStream.java
+1
-2
LobStorageMap.java
h2/src/main/org/h2/store/LobStorageMap.java
+35
-41
DataType.java
h2/src/main/org/h2/value/DataType.java
+5
-4
TestLob.java
h2/src/test/org/h2/test/db/TestLob.java
+12
-1
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
f3ec805a
...
...
@@ -21,6 +21,8 @@ Change Log
<h2>
Next Version (unreleased)
</h2>
<ul>
<li>
Issue #324: Deadlock when sending BLOBs over TCP
</li>
<li>
Fix for creating and accessing views in MULTITHREADED mode, test-case courtesy of Daniel Rosenbaum
</li>
<li>
Issue #266: Spatial index not updating, fixed by merging PR #267
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/Function.java
浏览文件 @
f3ec805a
...
...
@@ -1602,10 +1602,11 @@ public class Function extends Expression implements FunctionCall {
String
fileName
=
v0
.
getString
();
boolean
blob
=
args
.
length
==
1
;
try
{
long
fileLength
=
FileUtils
.
size
(
fileName
);
InputStream
in
=
new
AutoCloseInputStream
(
FileUtils
.
newInputStream
(
fileName
));
if
(
blob
)
{
result
=
database
.
getLobStorage
().
createBlob
(
in
,
-
1
);
result
=
database
.
getLobStorage
().
createBlob
(
in
,
fileLength
);
}
else
{
Reader
reader
;
if
(
v1
==
ValueNull
.
INSTANCE
)
{
...
...
@@ -1613,7 +1614,7 @@ public class Function extends Expression implements FunctionCall {
}
else
{
reader
=
new
InputStreamReader
(
in
,
v1
.
getString
());
}
result
=
database
.
getLobStorage
().
createClob
(
reader
,
-
1
);
result
=
database
.
getLobStorage
().
createClob
(
reader
,
fileLength
);
}
session
.
addTemporaryLob
(
result
);
}
catch
(
IOException
e
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/CountingReaderInputStream.java
浏览文件 @
f3ec805a
...
...
@@ -12,11 +12,10 @@ import java.nio.ByteBuffer;
import
java.nio.CharBuffer
;
import
java.nio.charset.CharsetEncoder
;
import
java.nio.charset.CodingErrorAction
;
import
org.h2.engine.Constants
;
/**
* An input stream that reads the data from a reader.
* An input stream that reads the data from a reader
and limits the number of bytes that can be read
.
*/
public
class
CountingReaderInputStream
extends
InputStream
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/LobStorageMap.java
浏览文件 @
f3ec805a
...
...
@@ -5,15 +5,12 @@
*/
package
org
.
h2
.
store
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Map.Entry
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Database
;
...
...
@@ -145,26 +142,21 @@ public class LobStorageMap implements LobStorageInterface {
public
Value
createBlob
(
InputStream
in
,
long
maxLength
)
{
init
();
int
type
=
Value
.
BLOB
;
if
(
maxLength
<
0
)
{
maxLength
=
Long
.
MAX_VALUE
;
}
int
max
=
(
int
)
Math
.
min
(
maxLength
,
database
.
getMaxLengthInplaceLob
());
try
{
if
(
max
!=
0
&&
max
<
Integer
.
MAX_VALUE
)
{
BufferedInputStream
b
=
new
BufferedInputStream
(
in
,
max
);
b
.
mark
(
max
)
;
byte
[]
small
=
new
byte
[
max
]
;
i
nt
len
=
IOUtils
.
readFully
(
b
,
small
,
max
);
if
(
len
<
max
)
{
if
(
len
<
small
.
length
)
{
small
=
Arrays
.
copyOf
(
small
,
len
);
}
return
ValueLobDb
.
createSmallLob
(
type
,
small
);
if
(
max
Length
!=
-
1
&&
maxLength
<=
database
.
getMaxLengthInplaceLob
())
{
b
yte
[]
small
=
new
byte
[(
int
)
maxLength
]
;
int
len
=
IOUtils
.
readFully
(
in
,
small
,
(
int
)
maxLength
)
;
i
f
(
len
>
maxLength
)
{
throw
new
IllegalStateException
(
"len > blobLength, "
+
len
+
" > "
+
maxLength
);
}
if
(
len
<
small
.
length
)
{
small
=
Arrays
.
copyOf
(
small
,
len
);
}
b
.
reset
();
in
=
b
;
return
ValueLobDb
.
createSmallLob
(
type
,
small
);
}
if
(
maxLength
!=
Long
.
MAX_VALUE
)
{
if
(
maxLength
!=
-
1
)
{
in
=
new
LimitInputStream
(
in
,
maxLength
);
}
return
createLob
(
in
,
type
);
...
...
@@ -179,32 +171,34 @@ public class LobStorageMap implements LobStorageInterface {
public
Value
createClob
(
Reader
reader
,
long
maxLength
)
{
init
();
int
type
=
Value
.
CLOB
;
if
(
maxLength
<
0
)
{
maxLength
=
Long
.
MAX_VALUE
;
}
int
max
=
(
int
)
Math
.
min
(
maxLength
,
database
.
getMaxLengthInplaceLob
());
try
{
if
(
max
!=
0
&&
max
<
Integer
.
MAX_VALUE
)
{
BufferedReader
b
=
new
BufferedReader
(
reader
,
max
);
b
.
mark
(
max
);
char
[]
small
=
new
char
[
max
];
int
len
=
IOUtils
.
readFully
(
b
,
small
,
max
);
if
(
len
<
max
)
{
if
(
len
<
small
.
length
)
{
small
=
Arrays
.
copyOf
(
small
,
len
);
}
byte
[]
utf8
=
new
String
(
small
,
0
,
len
).
getBytes
(
Constants
.
UTF8
);
return
ValueLobDb
.
createSmallLob
(
type
,
utf8
);
// we multiple by 3 here to get the worst-case size in bytes
if
(
maxLength
!=
-
1
&&
maxLength
*
3
<=
database
.
getMaxLengthInplaceLob
())
{
char
[]
small
=
new
char
[(
int
)
maxLength
];
int
len
=
IOUtils
.
readFully
(
reader
,
small
,
(
int
)
maxLength
);
if
(
len
>
maxLength
)
{
throw
new
IllegalStateException
(
"len > blobLength, "
+
len
+
" > "
+
maxLength
);
}
byte
[]
utf8
=
new
String
(
small
,
0
,
len
)
.
getBytes
(
Constants
.
UTF8
);
if
(
utf8
.
length
>
database
.
getMaxLengthInplaceLob
())
{
throw
new
IllegalStateException
(
"len > maxinplace, "
+
utf8
.
length
+
" > "
+
database
.
getMaxLengthInplaceLob
());
}
b
.
reset
();
reader
=
b
;
return
ValueLobDb
.
createSmallLob
(
type
,
utf8
);
}
if
(
maxLength
<
0
)
{
maxLength
=
Long
.
MAX_VALUE
;
}
CountingReaderInputStream
in
=
new
CountingReaderInputStream
(
reader
,
maxLength
);
CountingReaderInputStream
in
=
new
CountingReaderInputStream
(
reader
,
maxLength
);
ValueLobDb
lob
=
createLob
(
in
,
type
);
// the length is not correct
lob
=
ValueLobDb
.
create
(
type
,
database
,
lob
.
get
TableId
(),
lob
.
get
LobId
(),
null
,
in
.
getLength
());
lob
=
ValueLobDb
.
create
(
type
,
database
,
lob
.
getTableId
(),
lob
.
getLobId
(),
null
,
in
.
getLength
());
return
lob
;
}
catch
(
IllegalStateException
e
)
{
throw
DbException
.
get
(
ErrorCode
.
OBJECT_CLOSED
,
e
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/DataType.java
浏览文件 @
f3ec805a
...
...
@@ -1046,10 +1046,10 @@ public class DataType {
createClob
(
r
,
-
1
);
}
else
if
(
x
instanceof
java
.
sql
.
Clob
)
{
try
{
Reader
r
=
new
BufferedReader
(
((
java
.
sql
.
Clob
)
x
)
.
getCharacterStream
());
java
.
sql
.
Clob
clob
=
(
java
.
sql
.
Clob
)
x
;
Reader
r
=
new
BufferedReader
(
clob
.
getCharacterStream
());
return
session
.
getDataHandler
().
getLobStorage
().
createClob
(
r
,
-
1
);
createClob
(
r
,
clob
.
length
()
);
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
}
...
...
@@ -1058,8 +1058,9 @@ public class DataType {
createBlob
((
java
.
io
.
InputStream
)
x
,
-
1
);
}
else
if
(
x
instanceof
java
.
sql
.
Blob
)
{
try
{
java
.
sql
.
Blob
blob
=
(
java
.
sql
.
Blob
)
x
;
return
session
.
getDataHandler
().
getLobStorage
().
createBlob
(
((
java
.
sql
.
Blob
)
x
).
getBinaryStream
(),
-
1
);
createBlob
(
blob
.
getBinaryStream
(),
blob
.
length
()
);
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestLob.java
浏览文件 @
f3ec805a
...
...
@@ -23,7 +23,6 @@ import java.sql.SQLException;
import
java.sql.Savepoint
;
import
java.sql.Statement
;
import
java.util.Random
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.SysProperties
;
import
org.h2.jdbc.JdbcConnection
;
...
...
@@ -84,6 +83,7 @@ public class TestLob extends TestBase {
testDelete
();
testLobServerMemory
();
testUpdatingLobRow
();
testBufferedInputStreamBug
();
if
(
config
.
memory
)
{
return
;
}
...
...
@@ -1505,6 +1505,17 @@ public class TestLob extends TestBase {
conn
.
close
();
}
/** test a bug where the usage of BufferedInputStream in LobStorageMap was causing a deadlock */
private
void
testBufferedInputStreamBug
()
throws
SQLException
{
deleteDb
(
"lob"
);
JdbcConnection
conn
=
(
JdbcConnection
)
getConnection
(
"lob"
);
conn
.
createStatement
().
execute
(
"CREATE TABLE TEST(test BLOB)"
);
PreparedStatement
ps
=
conn
.
prepareStatement
(
"INSERT INTO TEST(test) VALUES(?)"
);
ps
.
setBlob
(
1
,
new
ByteArrayInputStream
(
new
byte
[
257
]));
ps
.
executeUpdate
();
conn
.
close
();
}
private
static
Reader
getRandomReader
(
int
len
,
int
seed
)
{
return
new
CharArrayReader
(
getRandomChars
(
len
,
seed
));
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论