Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
2ae49669
提交
2ae49669
authored
3月 11, 2009
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
--no commit message
上级
4c77fc1a
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
76 行增加
和
38 行删除
+76
-38
changelog.html
h2/src/docsrc/html/changelog.html
+2
-2
SysProperties.java
h2/src/main/org/h2/constant/SysProperties.java
+1
-1
FileObjectDiskChannel.java
h2/src/main/org/h2/store/fs/FileObjectDiskChannel.java
+7
-13
FileObjectDiskMapped.java
h2/src/main/org/h2/store/fs/FileObjectDiskMapped.java
+9
-13
FileSystemDisk.java
h2/src/main/org/h2/store/fs/FileSystemDisk.java
+18
-0
FileSystemDiskNio.java
h2/src/main/org/h2/store/fs/FileSystemDiskNio.java
+24
-7
FileSystemDiskNioMapped.java
h2/src/main/org/h2/store/fs/FileSystemDiskNioMapped.java
+5
-1
TableLink.java
h2/src/main/org/h2/table/TableLink.java
+6
-0
test.properties
h2/src/test/org/h2/test/bench/test.properties
+2
-0
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+2
-1
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
2ae49669
...
@@ -22,8 +22,8 @@ Change Log
...
@@ -22,8 +22,8 @@ Change Log
</li><li>
When converting CLOB to BINARY, each character resulted in one byte.
</li><li>
When converting CLOB to BINARY, each character resulted in one byte.
Now, the text is parsed as a hex as when converting VARCHAR.
Now, the text is parsed as a hex as when converting VARCHAR.
</li><li>
New experimental NIO storage mechanism with both FileChannel and
</li><li>
New experimental NIO storage mechanism with both FileChannel and
memory mapped files. To use it,
prepend nio: or nioMapped: to the file name.
memory mapped files. To use it,
use the file name prefix nio: or nioMapped:
Example:
jdbc:h2:nio:~/test. So far it looks like NIO storage is faster Mac OS
as in
jdbc:h2:nio:~/test. So far it looks like NIO storage is faster Mac OS
but slower on some Windows systems. Thanks a lot to Jan Kotek for the patch!
but slower on some Windows systems. Thanks a lot to Jan Kotek for the patch!
</li><li>
The functions BITOR, BITAND, BITXOR, and MOD now accept
</li><li>
The functions BITOR, BITAND, BITXOR, and MOD now accept
and return BIGINT instead of INT.
and return BIGINT instead of INT.
...
...
h2/src/main/org/h2/constant/SysProperties.java
浏览文件 @
2ae49669
...
@@ -323,7 +323,7 @@ public class SysProperties {
...
@@ -323,7 +323,7 @@ public class SysProperties {
/**
/**
* System property <code>h2.nioCleanerHack</code> (default: true).<br />
* System property <code>h2.nioCleanerHack</code> (default: true).<br />
* If possible, use a hack to unmap the mapped file. See also
* If possible, use a hack to un
-
map the mapped file. See also
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038
*/
*/
public
static
final
boolean
NIO_CLEANER_HACK
=
getBooleanSetting
(
"h2.nioCleanerHack"
,
true
);
public
static
final
boolean
NIO_CLEANER_HACK
=
getBooleanSetting
(
"h2.nioCleanerHack"
,
true
);
...
...
h2/src/main/org/h2/store/fs/FileObjectDiskChannel.java
浏览文件 @
2ae49669
...
@@ -22,8 +22,8 @@ public class FileObjectDiskChannel implements FileObject {
...
@@ -22,8 +22,8 @@ public class FileObjectDiskChannel implements FileObject {
FileObjectDiskChannel
(
String
fileName
,
String
mode
)
throws
FileNotFoundException
{
FileObjectDiskChannel
(
String
fileName
,
String
mode
)
throws
FileNotFoundException
{
this
.
name
=
fileName
;
this
.
name
=
fileName
;
RandomAccessFile
raf
=
new
RandomAccessFile
(
fileName
,
mode
);
RandomAccessFile
file
=
new
RandomAccessFile
(
fileName
,
mode
);
channel
=
raf
.
getChannel
();
channel
=
file
.
getChannel
();
}
}
public
void
close
()
throws
IOException
{
public
void
close
()
throws
IOException
{
...
@@ -46,10 +46,10 @@ public class FileObjectDiskChannel implements FileObject {
...
@@ -46,10 +46,10 @@ public class FileObjectDiskChannel implements FileObject {
if
(
len
==
0
)
{
if
(
len
==
0
)
{
return
;
return
;
}
}
if
(
channel
.
size
()
<=
off
+
len
)
{
// reading the size can reduce the performance
// TODO get size can degrade performance
// if (channel.size() <= off + len) {
throw
new
java
.
io
.
EOFException
();
//
throw new java.io.EOFException();
}
//
}
ByteBuffer
buf
=
ByteBuffer
.
wrap
(
b
);
ByteBuffer
buf
=
ByteBuffer
.
wrap
(
b
);
buf
.
position
(
off
);
buf
.
position
(
off
);
buf
.
limit
(
off
+
len
);
buf
.
limit
(
off
+
len
);
...
@@ -57,13 +57,10 @@ public class FileObjectDiskChannel implements FileObject {
...
@@ -57,13 +57,10 @@ public class FileObjectDiskChannel implements FileObject {
}
}
public
void
seek
(
long
pos
)
throws
IOException
{
public
void
seek
(
long
pos
)
throws
IOException
{
// System.out.println("seek");
channel
.
position
(
pos
);
channel
.
position
(
pos
);
}
}
public
void
setFileLength
(
long
newLength
)
throws
IOException
{
public
void
setFileLength
(
long
newLength
)
throws
IOException
{
// System.out.println("setFileLength");
// System.out.println(" "+channel.size()+" - "+channel.position());
if
(
newLength
<=
channel
.
size
())
{
if
(
newLength
<=
channel
.
size
())
{
long
oldPos
=
channel
.
position
();
long
oldPos
=
channel
.
position
();
channel
.
truncate
(
newLength
);
channel
.
truncate
(
newLength
);
...
@@ -72,20 +69,17 @@ public class FileObjectDiskChannel implements FileObject {
...
@@ -72,20 +69,17 @@ public class FileObjectDiskChannel implements FileObject {
}
}
channel
.
position
(
oldPos
);
channel
.
position
(
oldPos
);
}
else
{
}
else
{
// extend by writ
ting to
new location
// extend by writ
ing to the
new location
ByteBuffer
b
=
ByteBuffer
.
allocate
(
1
);
ByteBuffer
b
=
ByteBuffer
.
allocate
(
1
);
channel
.
write
(
b
,
newLength
-
1
);
channel
.
write
(
b
,
newLength
-
1
);
}
}
// System.out.println(" "+channel.size()+" - "+channel.position());
}
}
public
void
sync
()
throws
IOException
{
public
void
sync
()
throws
IOException
{
// System.out.println("sync");
channel
.
force
(
true
);
channel
.
force
(
true
);
}
}
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
// System.out.println("write");
ByteBuffer
buf
=
ByteBuffer
.
wrap
(
b
);
ByteBuffer
buf
=
ByteBuffer
.
wrap
(
b
);
buf
.
position
(
off
);
buf
.
position
(
off
);
buf
.
limit
(
off
+
len
);
buf
.
limit
(
off
+
len
);
...
...
h2/src/main/org/h2/store/fs/FileObjectDiskMapped.java
浏览文件 @
2ae49669
...
@@ -18,10 +18,9 @@ import org.h2.util.FileUtils;
...
@@ -18,10 +18,9 @@ import org.h2.util.FileUtils;
/**
/**
* FileObject which is using NIO MappedByteBuffer mapped to memory from file.
* FileObject which is using NIO MappedByteBuffer mapped to memory from file.
*/
*/
// TODO support files over 2 GB by using multiple buffers
// TODO howto dispose MappedByteBuffer?
public
class
FileObjectDiskMapped
implements
FileObject
{
public
class
FileObjectDiskMapped
implements
FileObject
{
// TODO support files over 2 GB by using multiple buffers
private
static
final
long
GC_TIMEOUT_MS
=
10000
;
private
static
final
long
GC_TIMEOUT_MS
=
10000
;
private
final
String
name
;
private
final
String
name
;
private
final
MapMode
mode
;
private
final
MapMode
mode
;
...
@@ -36,10 +35,10 @@ public class FileObjectDiskMapped implements FileObject {
...
@@ -36,10 +35,10 @@ public class FileObjectDiskMapped implements FileObject {
}
}
this
.
name
=
fileName
;
this
.
name
=
fileName
;
file
=
new
RandomAccessFile
(
fileName
,
mode
);
file
=
new
RandomAccessFile
(
fileName
,
mode
);
re
m
ap
();
re
M
ap
();
}
}
private
void
un
m
ap
()
{
private
void
un
M
ap
()
{
if
(
mapped
!=
null
)
{
if
(
mapped
!=
null
)
{
// first write all data
// first write all data
mapped
.
force
();
mapped
.
force
();
...
@@ -79,12 +78,10 @@ public class FileObjectDiskMapped implements FileObject {
...
@@ -79,12 +78,10 @@ public class FileObjectDiskMapped implements FileObject {
}
}
/**
/**
* remap byte buffer into memory, called when file size has changed or file
* Re-map byte buffer into memory, called when file size has changed or file
* was created
* was created.
*
* @throws IOException
*/
*/
private
void
re
m
ap
()
throws
IOException
{
private
void
re
M
ap
()
throws
IOException
{
if
(
file
.
length
()
>
Integer
.
MAX_VALUE
)
{
if
(
file
.
length
()
>
Integer
.
MAX_VALUE
)
{
throw
new
RuntimeException
(
"File over 2GB is not supported yet"
);
throw
new
RuntimeException
(
"File over 2GB is not supported yet"
);
}
}
...
@@ -92,7 +89,7 @@ public class FileObjectDiskMapped implements FileObject {
...
@@ -92,7 +89,7 @@ public class FileObjectDiskMapped implements FileObject {
if
(
mapped
!=
null
)
{
if
(
mapped
!=
null
)
{
oldPos
=
mapped
.
position
();
oldPos
=
mapped
.
position
();
mapped
.
force
();
mapped
.
force
();
un
m
ap
();
un
M
ap
();
}
}
// maps new MappedByteBuffer, old one is disposed during GC
// maps new MappedByteBuffer, old one is disposed during GC
...
@@ -104,8 +101,7 @@ public class FileObjectDiskMapped implements FileObject {
...
@@ -104,8 +101,7 @@ public class FileObjectDiskMapped implements FileObject {
}
}
public
void
close
()
throws
IOException
{
public
void
close
()
throws
IOException
{
unmap
();
unMap
();
file
.
close
();
file
.
close
();
file
=
null
;
file
=
null
;
}
}
...
@@ -132,7 +128,7 @@ public class FileObjectDiskMapped implements FileObject {
...
@@ -132,7 +128,7 @@ public class FileObjectDiskMapped implements FileObject {
public
void
setFileLength
(
long
newLength
)
throws
IOException
{
public
void
setFileLength
(
long
newLength
)
throws
IOException
{
FileUtils
.
setLength
(
file
,
newLength
);
FileUtils
.
setLength
(
file
,
newLength
);
re
m
ap
();
re
M
ap
();
}
}
public
void
sync
()
throws
IOException
{
public
void
sync
()
throws
IOException
{
...
...
h2/src/main/org/h2/store/fs/FileSystemDisk.java
浏览文件 @
2ae49669
...
@@ -47,6 +47,13 @@ public class FileSystemDisk extends FileSystem {
...
@@ -47,6 +47,13 @@ public class FileSystemDisk extends FileSystem {
return
new
File
(
fileName
).
length
();
return
new
File
(
fileName
).
length
();
}
}
/**
* Translate the file name to the native format.
* This will expand the home directory (~).
*
* @param fileName the file name
* @return the native file name
*/
protected
String
translateFileName
(
String
fileName
)
{
protected
String
translateFileName
(
String
fileName
)
{
if
(
fileName
!=
null
&&
fileName
.
startsWith
(
"~"
))
{
if
(
fileName
!=
null
&&
fileName
.
startsWith
(
"~"
))
{
String
userDir
=
SysProperties
.
USER_HOME
;
String
userDir
=
SysProperties
.
USER_HOME
;
...
@@ -82,6 +89,13 @@ public class FileSystemDisk extends FileSystem {
...
@@ -82,6 +89,13 @@ public class FileSystemDisk extends FileSystem {
throw
Message
.
getSQLException
(
ErrorCode
.
FILE_RENAME_FAILED_2
,
new
String
[]{
oldName
,
newName
});
throw
Message
.
getSQLException
(
ErrorCode
.
FILE_RENAME_FAILED_2
,
new
String
[]{
oldName
,
newName
});
}
}
/**
* Print a trace message if tracing is enabled.
*
* @param method the method
* @param fileName the file name
* @param o the object
*/
protected
void
trace
(
String
method
,
String
fileName
,
Object
o
)
{
protected
void
trace
(
String
method
,
String
fileName
,
Object
o
)
{
if
(
SysProperties
.
TRACE_IO
)
{
if
(
SysProperties
.
TRACE_IO
)
{
System
.
out
.
println
(
"FileSystem."
+
method
+
" "
+
fileName
+
" "
+
o
);
System
.
out
.
println
(
"FileSystem."
+
method
+
" "
+
fileName
+
" "
+
o
);
...
@@ -350,6 +364,10 @@ public class FileSystemDisk extends FileSystem {
...
@@ -350,6 +364,10 @@ public class FileSystemDisk extends FileSystem {
return
in
;
return
in
;
}
}
/**
* Call the garbage collection and run finalization. This close all files that
* were not closed, and are no longer referenced.
*/
protected
void
freeMemoryAndFinalize
()
{
protected
void
freeMemoryAndFinalize
()
{
trace
(
"freeMemoryAndFinalize"
,
null
,
null
);
trace
(
"freeMemoryAndFinalize"
,
null
,
null
);
Runtime
rt
=
Runtime
.
getRuntime
();
Runtime
rt
=
Runtime
.
getRuntime
();
...
...
h2/src/main/org/h2/store/fs/FileSystemDiskNio.java
浏览文件 @
2ae49669
...
@@ -25,12 +25,12 @@ public class FileSystemDiskNio extends FileSystemDisk {
...
@@ -25,12 +25,12 @@ public class FileSystemDiskNio extends FileSystemDisk {
public
String
createTempFile
(
String
name
,
String
suffix
,
boolean
deleteOnExit
,
boolean
inTempDir
)
public
String
createTempFile
(
String
name
,
String
suffix
,
boolean
deleteOnExit
,
boolean
inTempDir
)
throws
IOException
{
throws
IOException
{
String
file
=
super
.
createTempFile
(
name
,
suffix
,
deleteOnExit
,
inTempDir
);
String
file
=
super
.
createTempFile
(
name
,
suffix
,
deleteOnExit
,
inTempDir
);
return
FileSystem
.
PREFIX_NIO
+
file
;
return
getPrefix
()
+
file
;
}
}
protected
String
translateFileName
(
String
fileName
)
{
protected
String
translateFileName
(
String
fileName
)
{
if
(
fileName
.
startsWith
(
FileSystem
.
PREFIX_NIO
))
{
if
(
fileName
.
startsWith
(
getPrefix
()
))
{
fileName
=
fileName
.
substring
(
FileSystem
.
PREFIX_NIO
.
length
());
fileName
=
fileName
.
substring
(
getPrefix
()
.
length
());
}
}
return
super
.
translateFileName
(
fileName
);
return
super
.
translateFileName
(
fileName
);
}
}
...
@@ -40,23 +40,23 @@ public class FileSystemDiskNio extends FileSystemDisk {
...
@@ -40,23 +40,23 @@ public class FileSystemDiskNio extends FileSystemDisk {
}
}
public
String
normalize
(
String
fileName
)
throws
SQLException
{
public
String
normalize
(
String
fileName
)
throws
SQLException
{
return
FileSystem
.
PREFIX_NIO
+
super
.
normalize
(
fileName
);
return
getPrefix
()
+
super
.
normalize
(
fileName
);
}
}
public
String
[]
listFiles
(
String
path
)
throws
SQLException
{
public
String
[]
listFiles
(
String
path
)
throws
SQLException
{
String
[]
list
=
super
.
listFiles
(
path
);
String
[]
list
=
super
.
listFiles
(
path
);
for
(
int
i
=
0
;
list
!=
null
&&
i
<
list
.
length
;
i
++)
{
for
(
int
i
=
0
;
list
!=
null
&&
i
<
list
.
length
;
i
++)
{
list
[
i
]
=
FileSystem
.
PREFIX_NIO
+
list
[
i
];
list
[
i
]
=
getPrefix
()
+
list
[
i
];
}
}
return
list
;
return
list
;
}
}
public
String
getParent
(
String
fileName
)
{
public
String
getParent
(
String
fileName
)
{
return
FileSystem
.
PREFIX_NIO
+
super
.
getParent
(
fileName
);
return
getPrefix
()
+
super
.
getParent
(
fileName
);
}
}
public
String
getAbsolutePath
(
String
fileName
)
{
public
String
getAbsolutePath
(
String
fileName
)
{
return
FileSystem
.
PREFIX_NIO
+
super
.
getAbsolutePath
(
fileName
);
return
getPrefix
()
+
super
.
getAbsolutePath
(
fileName
);
}
}
public
FileObject
openFileObject
(
String
fileName
,
String
mode
)
throws
IOException
{
public
FileObject
openFileObject
(
String
fileName
,
String
mode
)
throws
IOException
{
...
@@ -77,6 +77,23 @@ public class FileSystemDiskNio extends FileSystemDisk {
...
@@ -77,6 +77,23 @@ public class FileSystemDiskNio extends FileSystemDisk {
return
f
;
return
f
;
}
}
/**
* Get the prefix for this file system.
*
* @return the prefix
*/
protected
String
getPrefix
()
{
return
FileSystem
.
PREFIX_NIO
;
}
/**
* Try to open a file with this name and mode.
*
* @param fileName the file name
* @param mode the open mode
* @return the file object
* @throws IOException if opening fails
*/
protected
FileObject
open
(
String
fileName
,
String
mode
)
throws
IOException
{
protected
FileObject
open
(
String
fileName
,
String
mode
)
throws
IOException
{
return
new
FileObjectDiskChannel
(
fileName
,
mode
);
return
new
FileObjectDiskChannel
(
fileName
,
mode
);
}
}
...
...
h2/src/main/org/h2/store/fs/FileSystemDiskNioMapped.java
浏览文件 @
2ae49669
...
@@ -12,7 +12,7 @@ import java.io.IOException;
...
@@ -12,7 +12,7 @@ import java.io.IOException;
* This file system stores files on disk and uses java.nio to access the files.
* This file system stores files on disk and uses java.nio to access the files.
* This class used memory mapped files.
* This class used memory mapped files.
*/
*/
public
class
FileSystemDiskNioMapped
extends
FileSystemDisk
{
public
class
FileSystemDiskNioMapped
extends
FileSystemDisk
Nio
{
private
static
final
FileSystemDiskNioMapped
INSTANCE
=
new
FileSystemDiskNioMapped
();
private
static
final
FileSystemDiskNioMapped
INSTANCE
=
new
FileSystemDiskNioMapped
();
...
@@ -20,6 +20,10 @@ public class FileSystemDiskNioMapped extends FileSystemDisk {
...
@@ -20,6 +20,10 @@ public class FileSystemDiskNioMapped extends FileSystemDisk {
return
INSTANCE
;
return
INSTANCE
;
}
}
protected
String
getPrefix
()
{
return
FileSystem
.
PREFIX_NIO_MAPPED
;
}
protected
FileObject
open
(
String
fileName
,
String
mode
)
throws
IOException
{
protected
FileObject
open
(
String
fileName
,
String
mode
)
throws
IOException
{
return
new
FileObjectDiskMapped
(
fileName
,
mode
);
return
new
FileObjectDiskMapped
(
fileName
,
mode
);
}
}
...
...
h2/src/main/org/h2/table/TableLink.java
浏览文件 @
2ae49669
...
@@ -523,6 +523,12 @@ public class TableLink extends Table {
...
@@ -523,6 +523,12 @@ public class TableLink extends Table {
return
ROW_COUNT_APPROXIMATION
;
return
ROW_COUNT_APPROXIMATION
;
}
}
/**
* Add this prepared statement to the list of cached statements.
*
* @param prep the prepared statement
* @param sql the SQL statement
*/
public
void
reusePreparedStatement
(
PreparedStatement
prep
,
String
sql
)
{
public
void
reusePreparedStatement
(
PreparedStatement
prep
,
String
sql
)
{
prepared
.
put
(
sql
,
prep
);
prepared
.
put
(
sql
,
prep
);
}
}
...
...
h2/src/test/org/h2/test/bench/test.properties
浏览文件 @
2ae49669
db1
=
H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3, sa, sa
db1
=
H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3, sa, sa
#db2 = H2 (nio), org.h2.Driver, jdbc:h2:nio:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3, sa, sa
#db3 = H2 (nioMapped), org.h2.Driver, jdbc:h2:nioMapped:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3, sa, sa
#db2 = H2 (MVCC), org.h2.Driver, jdbc:h2:data/test_mvcc;MVCC=TRUE, sa, sa
#db2 = H2 (MVCC), org.h2.Driver, jdbc:h2:data/test_mvcc;MVCC=TRUE, sa, sa
#xdb2 = H2 (XTEA), org.h2.Driver, jdbc:h2:data/test_xtea;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=XTEA, sa, sa 123
#xdb2 = H2 (XTEA), org.h2.Driver, jdbc:h2:data/test_xtea;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=XTEA, sa, sa 123
#xdb3 = H2 (AES), org.h2.Driver, jdbc:h2:data/test_aes;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=AES, sa, sa 123
#xdb3 = H2 (AES), org.h2.Driver, jdbc:h2:data/test_aes;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=AES, sa, sa 123
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
2ae49669
...
@@ -582,4 +582,5 @@ bot jot delicious rife appenders circles spelling cash sky ecm nuxeo poland
...
@@ -582,4 +582,5 @@ bot jot delicious rife appenders circles spelling cash sky ecm nuxeo poland
opengeospatial sfs symmetric obsolete failing parenthesis unloading refreshed
opengeospatial sfs symmetric obsolete failing parenthesis unloading refreshed
grails reloading slightly accepting deploying conflicting recovered counters
grails reloading slightly accepting deploying conflicting recovered counters
versus extracts squirrel misdirected rle looking arc addressed european
versus extracts squirrel misdirected rle looking arc addressed european
soerensen favicon glass restarts flexive fish
soerensen favicon glass restarts flexive fish resulted vpda mvc kotek jan
consistently springfuse
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论