Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
3fcb3c2a
提交
3fcb3c2a
authored
5月 17, 2013
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore: multiple issues were fixed
上级
667a4733
显示空白字符变更
内嵌
并排
正在显示
25 个修改的文件
包含
392 行增加
和
229 行删除
+392
-229
changelog.html
h2/src/docsrc/html/changelog.html
+2
-1
Command.java
h2/src/main/org/h2/command/Command.java
+2
-1
BackupCommand.java
h2/src/main/org/h2/command/dml/BackupCommand.java
+5
-2
Database.java
h2/src/main/org/h2/engine/Database.java
+19
-0
Session.java
h2/src/main/org/h2/engine/Session.java
+64
-20
SessionInterface.java
h2/src/main/org/h2/engine/SessionInterface.java
+5
-5
SessionRemote.java
h2/src/main/org/h2/engine/SessionRemote.java
+7
-8
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+1
-1
Cursor.java
h2/src/main/org/h2/mvstore/Cursor.java
+2
-1
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+9
-20
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+13
-5
MVPrimaryIndex.java
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
+4
-0
MVTable.java
h2/src/main/org/h2/mvstore/db/MVTable.java
+10
-7
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+58
-89
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+60
-37
ValueDataType.java
h2/src/main/org/h2/mvstore/db/ValueDataType.java
+3
-5
TcpServerThread.java
h2/src/main/org/h2/server/TcpServerThread.java
+2
-2
Data.java
h2/src/main/org/h2/store/Data.java
+2
-5
LobStorageFrontend.java
h2/src/main/org/h2/store/LobStorageFrontend.java
+2
-2
Table.java
h2/src/main/org/h2/table/Table.java
+1
-1
SourceCompiler.java
h2/src/main/org/h2/util/SourceCompiler.java
+4
-4
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+37
-4
TestMVTableEngine.java
h2/src/test/org/h2/test/store/TestMVTableEngine.java
+40
-8
TestTransactionStore.java
h2/src/test/org/h2/test/store/TestTransactionStore.java
+38
-0
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+2
-1
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
3fcb3c2a
...
@@ -23,6 +23,7 @@ Change Log
...
@@ -23,6 +23,7 @@ Change Log
in a strange exception of the type "column x must be included in the group by list".
in a strange exception of the type "column x must be included in the group by list".
</li><li>
Issue 454: Use Charset for type-safety.
</li><li>
Issue 454: Use Charset for type-safety.
</li><li>
Queries with both LIMIT and OFFSET could throw an IllegalArgumentException.
</li><li>
Queries with both LIMIT and OFFSET could throw an IllegalArgumentException.
</li><li>
MVStore: multiple issues were fixed: 460, 461, 462.
</li><li>
MVStore: larger stores (multiple GB) are now much faster.
</li><li>
MVStore: larger stores (multiple GB) are now much faster.
</li><li>
When using local temporary tables and not dropping them manually before closing the session,
</li><li>
When using local temporary tables and not dropping them manually before closing the session,
and then killing the process could result in a database that couldn't be opened (except when using
and then killing the process could result in a database that couldn't be opened (except when using
...
@@ -38,7 +39,7 @@ Change Log
...
@@ -38,7 +39,7 @@ Change Log
</li><li>
Issue 274: Sybase/MSSQLServer compatibility - Add GETDATE and CHARINDEX system functions
</li><li>
Issue 274: Sybase/MSSQLServer compatibility - Add GETDATE and CHARINDEX system functions
</li><li>
Issue 274: Sybase/MSSQLServer compatibility - swap parameters of CONVERT function.
</li><li>
Issue 274: Sybase/MSSQLServer compatibility - swap parameters of CONVERT function.
</li><li>
Issue 274: Sybase/MSSQLServer compatibility - support index clause e.g. "select * from test (index table1_index)"
</li><li>
Issue 274: Sybase/MSSQLServer compatibility - support index clause e.g. "select * from test (index table1_index)"
</li><li>
Fix bug in optimi
s
ing SELECT * FROM A WHERE X=1 OR X=2 OR X=3 into SELECT * FROM A WHERE X IN (1,2,3)
</li><li>
Fix bug in optimi
z
ing SELECT * FROM A WHERE X=1 OR X=2 OR X=3 into SELECT * FROM A WHERE X IN (1,2,3)
</li><li>
Issue 442: groovy patch for SourceCompiler (function ALIAS)
</li><li>
Issue 442: groovy patch for SourceCompiler (function ALIAS)
</li><li>
Issue 459: Improve LOB documentation
</li><li>
Issue 459: Improve LOB documentation
</li></ul>
</li></ul>
...
...
h2/src/main/org/h2/command/Command.java
浏览文件 @
3fcb3c2a
...
@@ -143,6 +143,7 @@ public abstract class Command implements CommandInterface {
...
@@ -143,6 +143,7 @@ public abstract class Command implements CommandInterface {
}
}
private
void
stop
()
{
private
void
stop
()
{
session
.
endStatement
();
session
.
closeTemporaryResults
();
session
.
closeTemporaryResults
();
session
.
setCurrentCommand
(
null
);
session
.
setCurrentCommand
(
null
);
if
(!
isTransactional
())
{
if
(!
isTransactional
())
{
...
@@ -226,7 +227,7 @@ public abstract class Command implements CommandInterface {
...
@@ -226,7 +227,7 @@ public abstract class Command implements CommandInterface {
}
}
}
}
synchronized
(
sync
)
{
synchronized
(
sync
)
{
int
rollback
=
session
.
getUndoLogPos
();
Session
.
Savepoint
rollback
=
session
.
setSavepoint
();
session
.
setCurrentCommand
(
this
);
session
.
setCurrentCommand
(
this
);
try
{
try
{
while
(
true
)
{
while
(
true
)
{
...
...
h2/src/main/org/h2/command/dml/BackupCommand.java
浏览文件 @
3fcb3c2a
...
@@ -21,7 +21,7 @@ import org.h2.engine.Database;
...
@@ -21,7 +21,7 @@ import org.h2.engine.Database;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
;
import
org.h2.expression.Expression
;
import
org.h2.expression.Expression
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.db.MVTableEngine
;
import
org.h2.mvstore.db.MVTableEngine
.Store
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.ResultInterface
;
import
org.h2.store.FileLister
;
import
org.h2.store.FileLister
;
import
org.h2.store.PageStore
;
import
org.h2.store.PageStore
;
...
@@ -58,7 +58,10 @@ public class BackupCommand extends Prepared {
...
@@ -58,7 +58,10 @@ public class BackupCommand extends Prepared {
throw
DbException
.
get
(
ErrorCode
.
DATABASE_IS_NOT_PERSISTENT
);
throw
DbException
.
get
(
ErrorCode
.
DATABASE_IS_NOT_PERSISTENT
);
}
}
try
{
try
{
MVTableEngine
.
flush
(
db
);
Store
store
=
db
.
getMvStore
();
if
(
store
!=
null
)
{
store
.
store
();
}
String
name
=
db
.
getName
();
String
name
=
db
.
getName
();
name
=
FileUtils
.
getName
(
name
);
name
=
FileUtils
.
getName
(
name
);
OutputStream
zip
=
FileUtils
.
newOutputStream
(
fileName
,
false
);
OutputStream
zip
=
FileUtils
.
newOutputStream
(
fileName
,
false
);
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
3fcb3c2a
...
@@ -30,6 +30,7 @@ import org.h2.jdbc.JdbcConnection;
...
@@ -30,6 +30,7 @@ import org.h2.jdbc.JdbcConnection;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.message.Trace
;
import
org.h2.message.Trace
;
import
org.h2.message.TraceSystem
;
import
org.h2.message.TraceSystem
;
import
org.h2.mvstore.db.MVTableEngine
;
import
org.h2.result.Row
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SearchRow
;
import
org.h2.schema.Schema
;
import
org.h2.schema.Schema
;
...
@@ -173,6 +174,7 @@ public class Database implements DataHandler {
...
@@ -173,6 +174,7 @@ public class Database implements DataHandler {
private
final
DbSettings
dbSettings
;
private
final
DbSettings
dbSettings
;
private
final
int
reconnectCheckDelay
;
private
final
int
reconnectCheckDelay
;
private
int
logMode
;
private
int
logMode
;
private
MVTableEngine
.
Store
mvStore
;
public
Database
(
ConnectionInfo
ci
,
String
cipher
)
{
public
Database
(
ConnectionInfo
ci
,
String
cipher
)
{
String
name
=
ci
.
getName
();
String
name
=
ci
.
getName
();
...
@@ -263,6 +265,14 @@ public class Database implements DataHandler {
...
@@ -263,6 +265,14 @@ public class Database implements DataHandler {
powerOffCount
=
count
;
powerOffCount
=
count
;
}
}
public
MVTableEngine
.
Store
getMvStore
()
{
return
mvStore
;
}
public
void
setMvStore
(
MVTableEngine
.
Store
mvStore
)
{
this
.
mvStore
=
mvStore
;
}
/**
/**
* Check if two values are equal with the current comparison mode.
* Check if two values are equal with the current comparison mode.
*
*
...
@@ -406,6 +416,9 @@ public class Database implements DataHandler {
...
@@ -406,6 +416,9 @@ public class Database implements DataHandler {
try
{
try
{
powerOffCount
=
-
1
;
powerOffCount
=
-
1
;
stopWriter
();
stopWriter
();
if
(
mvStore
!=
null
)
{
mvStore
.
closeImmediately
();
}
if
(
pageStore
!=
null
)
{
if
(
pageStore
!=
null
)
{
try
{
try
{
pageStore
.
close
();
pageStore
.
close
();
...
@@ -1218,6 +1231,9 @@ public class Database implements DataHandler {
...
@@ -1218,6 +1231,9 @@ public class Database implements DataHandler {
}
}
}
}
reconnectModified
(
false
);
reconnectModified
(
false
);
if
(
mvStore
!=
null
)
{
mvStore
.
close
();
}
closeFiles
();
closeFiles
();
if
(
persistent
&&
lock
==
null
&&
fileLockMethod
!=
FileLock
.
LOCK_NO
&&
fileLockMethod
!=
FileLock
.
LOCK_FS
)
{
if
(
persistent
&&
lock
==
null
&&
fileLockMethod
!=
FileLock
.
LOCK_NO
&&
fileLockMethod
!=
FileLock
.
LOCK_FS
)
{
// everything already closed (maybe in checkPowerOff)
// everything already closed (maybe in checkPowerOff)
...
@@ -1251,6 +1267,9 @@ public class Database implements DataHandler {
...
@@ -1251,6 +1267,9 @@ public class Database implements DataHandler {
private
synchronized
void
closeFiles
()
{
private
synchronized
void
closeFiles
()
{
try
{
try
{
if
(
mvStore
!=
null
)
{
mvStore
.
closeImmediately
();
}
if
(
pageStore
!=
null
)
{
if
(
pageStore
!=
null
)
{
pageStore
.
close
();
pageStore
.
close
();
pageStore
=
null
;
pageStore
=
null
;
...
...
h2/src/main/org/h2/engine/Session.java
浏览文件 @
3fcb3c2a
...
@@ -10,6 +10,8 @@ import java.util.ArrayList;
...
@@ -10,6 +10,8 @@ import java.util.ArrayList;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.HashSet
;
import
java.util.Random
;
import
java.util.Random
;
import
java.util.Set
;
import
org.h2.command.Command
;
import
org.h2.command.Command
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.Parser
;
import
org.h2.command.Parser
;
...
@@ -23,7 +25,7 @@ import org.h2.jdbc.JdbcConnection;
...
@@ -23,7 +25,7 @@ import org.h2.jdbc.JdbcConnection;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.message.Trace
;
import
org.h2.message.Trace
;
import
org.h2.message.TraceSystem
;
import
org.h2.message.TraceSystem
;
import
org.h2.mvstore.db.
TransactionStor
e
;
import
org.h2.mvstore.db.
MVTabl
e
;
import
org.h2.mvstore.db.TransactionStore.Transaction
;
import
org.h2.mvstore.db.TransactionStore.Transaction
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.Row
;
import
org.h2.result.Row
;
...
@@ -72,7 +74,7 @@ public class Session extends SessionWithState {
...
@@ -72,7 +74,7 @@ public class Session extends SessionWithState {
private
Value
lastScopeIdentity
=
ValueLong
.
get
(
0
);
private
Value
lastScopeIdentity
=
ValueLong
.
get
(
0
);
private
int
firstUncommittedLog
=
Session
.
LOG_WRITTEN
;
private
int
firstUncommittedLog
=
Session
.
LOG_WRITTEN
;
private
int
firstUncommittedPos
=
Session
.
LOG_WRITTEN
;
private
int
firstUncommittedPos
=
Session
.
LOG_WRITTEN
;
private
HashMap
<
String
,
Integer
>
savepoints
;
private
HashMap
<
String
,
Savepoint
>
savepoints
;
private
HashMap
<
String
,
Table
>
localTempTables
;
private
HashMap
<
String
,
Table
>
localTempTables
;
private
HashMap
<
String
,
Index
>
localTempTableIndexes
;
private
HashMap
<
String
,
Index
>
localTempTableIndexes
;
private
HashMap
<
String
,
Constraint
>
localTempTableConstraints
;
private
HashMap
<
String
,
Constraint
>
localTempTableConstraints
;
...
@@ -104,6 +106,7 @@ public class Session extends SessionWithState {
...
@@ -104,6 +106,7 @@ public class Session extends SessionWithState {
private
int
objectId
;
private
int
objectId
;
private
final
int
queryCacheSize
;
private
final
int
queryCacheSize
;
private
SmallLRUCache
<
String
,
Command
>
queryCache
;
private
SmallLRUCache
<
String
,
Command
>
queryCache
;
private
Transaction
transaction
;
private
Transaction
transaction
;
private
long
startStatement
=
-
1
;
private
long
startStatement
=
-
1
;
...
@@ -514,13 +517,19 @@ public class Session extends SessionWithState {
...
@@ -514,13 +517,19 @@ public class Session extends SessionWithState {
public
void
rollback
()
{
public
void
rollback
()
{
checkCommitRollback
();
checkCommitRollback
();
if
(
transaction
!=
null
)
{
if
(
transaction
!=
null
)
{
Set
<
String
>
changed
=
transaction
.
getChangedMaps
(
0
);
for
(
MVTable
t
:
database
.
getMvStore
().
getTables
())
{
if
(
changed
.
contains
(
t
.
getMapName
()))
{
t
.
setModified
();
}
}
transaction
.
rollback
();
transaction
.
rollback
();
transaction
=
null
;
transaction
=
null
;
}
}
currentTransactionName
=
null
;
currentTransactionName
=
null
;
boolean
needCommit
=
false
;
boolean
needCommit
=
false
;
if
(
undoLog
.
size
()
>
0
)
{
if
(
undoLog
.
size
()
>
0
)
{
rollbackTo
(
0
,
false
);
rollbackTo
(
null
,
false
);
needCommit
=
true
;
needCommit
=
true
;
}
}
if
(
locks
.
size
()
>
0
||
needCommit
)
{
if
(
locks
.
size
()
>
0
||
needCommit
)
{
...
@@ -537,30 +546,49 @@ public class Session extends SessionWithState {
...
@@ -537,30 +546,49 @@ public class Session extends SessionWithState {
/**
/**
* Partially roll back the current transaction.
* Partially roll back the current transaction.
*
*
* @param
index the position
to which should be rolled back
* @param
savepoint the savepoint
to which should be rolled back
* @param trimToSize if the list should be trimmed
* @param trimToSize if the list should be trimmed
*/
*/
public
void
rollbackTo
(
int
index
,
boolean
trimToSize
)
{
public
void
rollbackTo
(
Savepoint
savepoint
,
boolean
trimToSize
)
{
int
index
=
savepoint
==
null
?
0
:
savepoint
.
logIndex
;
while
(
undoLog
.
size
()
>
index
)
{
while
(
undoLog
.
size
()
>
index
)
{
UndoLogRecord
entry
=
undoLog
.
getLast
();
UndoLogRecord
entry
=
undoLog
.
getLast
();
entry
.
undo
(
this
);
entry
.
undo
(
this
);
undoLog
.
removeLast
(
trimToSize
);
undoLog
.
removeLast
(
trimToSize
);
}
}
if
(
transaction
!=
null
)
{
Set
<
String
>
changed
=
transaction
.
getChangedMaps
(
savepoint
.
transactionSavepoint
);
for
(
MVTable
t
:
database
.
getMvStore
().
getTables
())
{
if
(
changed
.
contains
(
t
.
getMapName
()))
{
t
.
setModified
();
}
}
transaction
.
rollbackToSavepoint
(
savepoint
.
transactionSavepoint
);
}
if
(
savepoints
!=
null
)
{
if
(
savepoints
!=
null
)
{
String
[]
names
=
new
String
[
savepoints
.
size
()];
String
[]
names
=
new
String
[
savepoints
.
size
()];
savepoints
.
keySet
().
toArray
(
names
);
savepoints
.
keySet
().
toArray
(
names
);
for
(
String
name
:
names
)
{
for
(
String
name
:
names
)
{
Integer
savepointIndex
=
savepoints
.
get
(
name
);
Savepoint
sp
=
savepoints
.
get
(
name
);
if
(
savepointIndex
.
intValue
()
>
index
)
{
int
savepointIndex
=
sp
.
logIndex
;
if
(
savepointIndex
>
index
)
{
savepoints
.
remove
(
name
);
savepoints
.
remove
(
name
);
}
}
}
}
}
}
}
}
@Override
public
boolean
hasPendingTransaction
()
{
public
int
getUndoLogPos
()
{
return
undoLog
.
size
()
>
0
;
return
undoLog
.
size
();
}
public
Savepoint
setSavepoint
()
{
Savepoint
sp
=
new
Savepoint
();
sp
.
logIndex
=
undoLog
.
size
();
if
(
database
.
getMvStore
()
!=
null
)
{
sp
.
transactionSavepoint
=
getStatementSavepoint
();
}
return
sp
;
}
}
public
int
getId
()
{
public
int
getId
()
{
...
@@ -791,7 +819,12 @@ public class Session extends SessionWithState {
...
@@ -791,7 +819,12 @@ public class Session extends SessionWithState {
if
(
savepoints
==
null
)
{
if
(
savepoints
==
null
)
{
savepoints
=
database
.
newStringMap
();
savepoints
=
database
.
newStringMap
();
}
}
savepoints
.
put
(
name
,
getUndoLogPos
());
Savepoint
sp
=
new
Savepoint
();
sp
.
logIndex
=
undoLog
.
size
();
if
(
database
.
getMvStore
()
!=
null
)
{
sp
.
transactionSavepoint
=
getStatementSavepoint
();
}
savepoints
.
put
(
name
,
sp
);
}
}
/**
/**
...
@@ -804,12 +837,11 @@ public class Session extends SessionWithState {
...
@@ -804,12 +837,11 @@ public class Session extends SessionWithState {
if
(
savepoints
==
null
)
{
if
(
savepoints
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
SAVEPOINT_IS_INVALID_1
,
name
);
throw
DbException
.
get
(
ErrorCode
.
SAVEPOINT_IS_INVALID_1
,
name
);
}
}
Integer
savepointIndex
=
savepoints
.
get
(
name
);
Savepoint
savepoint
=
savepoints
.
get
(
name
);
if
(
savepoint
Index
==
null
)
{
if
(
savepoint
==
null
)
{
throw
DbException
.
get
(
ErrorCode
.
SAVEPOINT_IS_INVALID_1
,
name
);
throw
DbException
.
get
(
ErrorCode
.
SAVEPOINT_IS_INVALID_1
,
name
);
}
}
int
i
=
savepointIndex
.
intValue
();
rollbackTo
(
savepoint
,
false
);
rollbackTo
(
i
,
false
);
}
}
/**
/**
...
@@ -1274,12 +1306,11 @@ public class Session extends SessionWithState {
...
@@ -1274,12 +1306,11 @@ public class Session extends SessionWithState {
/**
/**
* Get the transaction to use for this session.
* Get the transaction to use for this session.
*
*
* @param store the store
* @return the transaction
* @return the transaction
*/
*/
public
Transaction
getTransaction
(
TransactionStore
store
)
{
public
Transaction
getTransaction
()
{
if
(
transaction
==
null
)
{
if
(
transaction
==
null
)
{
transaction
=
store
.
begin
();
transaction
=
database
.
getMvStore
().
getTransactionStore
()
.
begin
();
startStatement
=
-
1
;
startStatement
=
-
1
;
}
}
return
transaction
;
return
transaction
;
...
@@ -1287,9 +1318,22 @@ public class Session extends SessionWithState {
...
@@ -1287,9 +1318,22 @@ public class Session extends SessionWithState {
public
long
getStatementSavepoint
()
{
public
long
getStatementSavepoint
()
{
if
(
startStatement
==
-
1
)
{
if
(
startStatement
==
-
1
)
{
startStatement
=
transaction
.
setSavepoint
();
startStatement
=
getTransaction
()
.
setSavepoint
();
}
}
return
startStatement
;
return
startStatement
;
}
}
public
void
endStatement
()
{
startStatement
=
-
1
;
}
/**
* Represents a savepoint (a position in a transaction to where one can roll
* back to).
*/
public
static
class
Savepoint
{
int
logIndex
;
long
transactionSavepoint
;
}
}
}
h2/src/main/org/h2/engine/SessionInterface.java
浏览文件 @
3fcb3c2a
...
@@ -69,11 +69,11 @@ public interface SessionInterface extends Closeable {
...
@@ -69,11 +69,11 @@ public interface SessionInterface extends Closeable {
DataHandler
getDataHandler
();
DataHandler
getDataHandler
();
/**
/**
*
Get the undo log posi
tion.
*
Check whether this session has a pending transac
tion.
*
*
* @return t
he position (0 means no pending transaction)
* @return t
rue if it has
*/
*/
int
getUndoLogPos
();
boolean
hasPendingTransaction
();
/**
/**
* Cancel the current or next command (called when closing a connection).
* Cancel the current or next command (called when closing a connection).
...
...
h2/src/main/org/h2/engine/SessionRemote.java
浏览文件 @
3fcb3c2a
...
@@ -56,7 +56,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
...
@@ -56,7 +56,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
public
static
final
int
SESSION_CANCEL_STATEMENT
=
13
;
public
static
final
int
SESSION_CANCEL_STATEMENT
=
13
;
public
static
final
int
SESSION_CHECK_KEY
=
14
;
public
static
final
int
SESSION_CHECK_KEY
=
14
;
public
static
final
int
SESSION_SET_AUTOCOMMIT
=
15
;
public
static
final
int
SESSION_SET_AUTOCOMMIT
=
15
;
public
static
final
int
SESSION_
UNDO_LOG_POS
=
16
;
public
static
final
int
SESSION_
HAS_PENDING_TRANSACTION
=
16
;
public
static
final
int
LOB_READ
=
17
;
public
static
final
int
LOB_READ
=
17
;
public
static
final
int
STATUS_ERROR
=
0
;
public
static
final
int
STATUS_ERROR
=
0
;
...
@@ -123,23 +123,22 @@ public class SessionRemote extends SessionWithState implements DataHandler {
...
@@ -123,23 +123,22 @@ public class SessionRemote extends SessionWithState implements DataHandler {
return
trans
;
return
trans
;
}
}
@Override
public
boolean
hasPendingTransaction
()
{
public
int
getUndoLogPos
()
{
if
(
clientVersion
<
Constants
.
TCP_PROTOCOL_VERSION_10
)
{
if
(
clientVersion
<
Constants
.
TCP_PROTOCOL_VERSION_10
)
{
return
1
;
return
true
;
}
}
for
(
int
i
=
0
,
count
=
0
;
i
<
transferList
.
size
();
i
++)
{
for
(
int
i
=
0
,
count
=
0
;
i
<
transferList
.
size
();
i
++)
{
Transfer
transfer
=
transferList
.
get
(
i
);
Transfer
transfer
=
transferList
.
get
(
i
);
try
{
try
{
traceOperation
(
"SESSION_
UNDO_LOG_POS
"
,
0
);
traceOperation
(
"SESSION_
HAS_PENDING_TRANSACTION
"
,
0
);
transfer
.
writeInt
(
SessionRemote
.
SESSION_
UNDO_LOG_POS
);
transfer
.
writeInt
(
SessionRemote
.
SESSION_
HAS_PENDING_TRANSACTION
);
done
(
transfer
);
done
(
transfer
);
return
transfer
.
readInt
();
return
transfer
.
readInt
()
!=
0
;
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
removeServer
(
e
,
i
--,
++
count
);
removeServer
(
e
,
i
--,
++
count
);
}
}
}
}
return
1
;
return
true
;
}
}
@Override
@Override
...
...
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
3fcb3c2a
...
@@ -346,7 +346,7 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -346,7 +346,7 @@ public class JdbcConnection extends TraceObject implements Connection {
try
{
try
{
if
(!
session
.
isClosed
())
{
if
(!
session
.
isClosed
())
{
try
{
try
{
if
(
session
.
getUndoLogPos
()
!=
0
)
{
if
(
session
.
hasPendingTransaction
()
)
{
// roll back unless that would require to re-connect
// roll back unless that would require to re-connect
// (the transaction can't be rolled back after re-connecting)
// (the transaction can't be rolled back after re-connecting)
if
(!
session
.
isReconnectNeeded
(
true
))
{
if
(!
session
.
isReconnectNeeded
(
true
))
{
...
...
h2/src/main/org/h2/mvstore/Cursor.java
浏览文件 @
3fcb3c2a
...
@@ -64,6 +64,7 @@ public class Cursor<K> implements Iterator<K> {
...
@@ -64,6 +64,7 @@ public class Cursor<K> implements Iterator<K> {
}
}
long
index
=
map
.
getKeyIndex
(
current
);
long
index
=
map
.
getKeyIndex
(
current
);
K
k
=
map
.
getKey
(
index
+
n
);
K
k
=
map
.
getKey
(
index
+
n
);
pos
=
null
;
min
(
root
,
k
);
min
(
root
,
k
);
fetchNext
();
fetchNext
();
}
}
...
@@ -76,7 +77,7 @@ public class Cursor<K> implements Iterator<K> {
...
@@ -76,7 +77,7 @@ public class Cursor<K> implements Iterator<K> {
/**
/**
* Fetch the next entry that is equal or larger than the given key, starting
* Fetch the next entry that is equal or larger than the given key, starting
* from the given page.
* from the given page.
This method retains the stack.
*
*
* @param p the page to start
* @param p the page to start
* @param from the key to search
* @param from the key to search
...
...
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
3fcb3c2a
...
@@ -328,7 +328,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -328,7 +328,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* Get the smallest key that is larger than the given key, or null if no
* Get the smallest key that is larger than the given key, or null if no
* such key exists.
* such key exists.
*
*
* @param key the key
(may not be null)
* @param key the key
* @return the result
* @return the result
*/
*/
public
K
higherKey
(
K
key
)
{
public
K
higherKey
(
K
key
)
{
...
@@ -338,7 +338,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -338,7 +338,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
/**
/**
* Get the smallest key that is larger or equal to this key.
* Get the smallest key that is larger or equal to this key.
*
*
* @param key the key
(may not be null)
* @param key the key
* @return the result
* @return the result
*/
*/
public
K
ceilingKey
(
K
key
)
{
public
K
ceilingKey
(
K
key
)
{
...
@@ -348,7 +348,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -348,7 +348,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
/**
/**
* Get the largest key that is smaller or equal to this key.
* Get the largest key that is smaller or equal to this key.
*
*
* @param key the key
(may not be null)
* @param key the key
* @return the result
* @return the result
*/
*/
public
K
floorKey
(
K
key
)
{
public
K
floorKey
(
K
key
)
{
...
@@ -359,7 +359,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -359,7 +359,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* Get the largest key that is smaller than the given key, or null if no
* Get the largest key that is smaller than the given key, or null if no
* such key exists.
* such key exists.
*
*
* @param key the key
(may not be null)
* @param key the key
* @return the result
* @return the result
*/
*/
public
K
lowerKey
(
K
key
)
{
public
K
lowerKey
(
K
key
)
{
...
@@ -372,22 +372,16 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -372,22 +372,16 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* @param key the key
* @param key the key
* @param min whether to retrieve the smallest key
* @param min whether to retrieve the smallest key
* @param excluding if the given upper/lower bound is exclusive
* @param excluding if the given upper/lower bound is exclusive
* @return the key, or null if
the map is empty
* @return the key, or null if
no such key exists
*/
*/
protected
K
getMinMax
(
K
key
,
boolean
min
,
boolean
excluding
)
{
protected
K
getMinMax
(
K
key
,
boolean
min
,
boolean
excluding
)
{
checkOpen
();
checkOpen
();
if
(
size
()
==
0
)
{
return
null
;
}
return
getMinMax
(
root
,
key
,
min
,
excluding
);
return
getMinMax
(
root
,
key
,
min
,
excluding
);
}
}
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
private
K
getMinMax
(
Page
p
,
K
key
,
boolean
min
,
boolean
excluding
)
{
private
K
getMinMax
(
Page
p
,
K
key
,
boolean
min
,
boolean
excluding
)
{
if
(
p
.
isLeaf
())
{
if
(
p
.
isLeaf
())
{
if
(
key
==
null
)
{
return
(
K
)
p
.
getKey
(
min
?
0
:
p
.
getKeyCount
()
-
1
);
}
int
x
=
p
.
binarySearch
(
key
);
int
x
=
p
.
binarySearch
(
key
);
if
(
x
<
0
)
{
if
(
x
<
0
)
{
x
=
-
x
-
(
min
?
2
:
1
);
x
=
-
x
-
(
min
?
2
:
1
);
...
@@ -399,17 +393,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -399,17 +393,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
}
}
return
(
K
)
p
.
getKey
(
x
);
return
(
K
)
p
.
getKey
(
x
);
}
}
int
x
;
int
x
=
p
.
binarySearch
(
key
);
if
(
key
==
null
)
{
x
=
min
?
0
:
p
.
getKeyCount
()
-
1
;
}
else
{
x
=
p
.
binarySearch
(
key
);
if
(
x
<
0
)
{
if
(
x
<
0
)
{
x
=
-
x
-
1
;
x
=
-
x
-
1
;
}
else
{
}
else
{
x
++;
x
++;
}
}
}
while
(
true
)
{
while
(
true
)
{
if
(
x
<
0
||
x
>=
p
.
getChildPageCount
())
{
if
(
x
<
0
||
x
>=
p
.
getChildPageCount
())
{
return
null
;
return
null
;
...
...
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
3fcb3c2a
...
@@ -44,6 +44,12 @@ H:3,...
...
@@ -44,6 +44,12 @@ H:3,...
TODO:
TODO:
TestMVStoreDataLoss
TransactionStore:
- support reading the undo log
MVStore:
- rolling docs review: at convert "Features" to top-level (linked) entries
- rolling docs review: at convert "Features" to top-level (linked) entries
- additional test async write / read algorithm for speed and errors
- additional test async write / read algorithm for speed and errors
- move setters to the builder, except for setRetainVersion, setReuseSpace,
- move setters to the builder, except for setRetainVersion, setReuseSpace,
...
@@ -94,10 +100,12 @@ TODO:
...
@@ -94,10 +100,12 @@ TODO:
- to save space when persisting very small transactions,
- to save space when persisting very small transactions,
-- use a transaction log where only the deltas are stored
-- use a transaction log where only the deltas are stored
- serialization for lists, sets, sets, sorted sets, maps, sorted maps
- serialization for lists, sets, sets, sorted sets, maps, sorted maps
- maybe rename 'rollback' to 'revert'
- maybe rename 'rollback' to 'revert'
to distinguish from transactions
- support other compression algorithms (deflate, LZ4,...)
- support other compression algorithms (deflate, LZ4,...)
- only retain the last version, unless explicitly set (setRetainVersion)
- only retain the last version, unless explicitly set (setRetainVersion)
- unit test for the FreeSpaceList; maybe find a simpler implementation
- unit test for the FreeSpaceList; maybe find a simpler implementation
- support opening (existing) maps by id
- more consistent null handling (keys/values sometimes may be null)
*/
*/
...
@@ -751,18 +759,18 @@ public class MVStore {
...
@@ -751,18 +759,18 @@ public class MVStore {
* Commit the changes. This method marks the changes as committed and
* Commit the changes. This method marks the changes as committed and
* increments the version.
* increments the version.
* <p>
* <p>
* Unless the write delay is
disabled
, this method does not write to the
* Unless the write delay is
set to 0
, this method does not write to the
* file. Instead, data is written after the delay, manually by calling the
* file. Instead, data is written after the delay, manually by calling the
* store method, when the write buffer is full, or when closing the store.
* store method, when the write buffer is full, or when closing the store.
*
*
* @return the new version
* @return the new version
*/
*/
public
long
commit
()
{
public
long
commit
()
{
if
(
writeDelay
==
0
)
{
return
store
(
true
);
}
long
v
=
++
currentVersion
;
long
v
=
++
currentVersion
;
lastCommittedVersion
=
v
;
lastCommittedVersion
=
v
;
if
(
writeDelay
==
0
)
{
store
(
false
);
}
return
v
;
return
v
;
}
}
...
...
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
浏览文件 @
3fcb3c2a
...
@@ -269,6 +269,10 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -269,6 +269,10 @@ public class MVPrimaryIndex extends BaseIndex {
return
0
;
return
0
;
}
}
public
String
getMapName
()
{
return
mapName
;
}
@Override
@Override
public
void
checkRename
()
{
public
void
checkRename
()
{
// ok
// ok
...
...
h2/src/main/org/h2/mvstore/db/MVTable.java
浏览文件 @
3fcb3c2a
...
@@ -47,8 +47,6 @@ import org.h2.value.Value;
...
@@ -47,8 +47,6 @@ import org.h2.value.Value;
*/
*/
public
class
MVTable
extends
TableBase
{
public
class
MVTable
extends
TableBase
{
private
final
String
storeName
;
private
final
TransactionStore
store
;
private
MVPrimaryIndex
primaryIndex
;
private
MVPrimaryIndex
primaryIndex
;
private
ArrayList
<
Index
>
indexes
=
New
.
arrayList
();
private
ArrayList
<
Index
>
indexes
=
New
.
arrayList
();
private
long
lastModificationId
;
private
long
lastModificationId
;
...
@@ -61,6 +59,8 @@ public class MVTable extends TableBase {
...
@@ -61,6 +59,8 @@ public class MVTable extends TableBase {
private
boolean
containsLargeObject
;
private
boolean
containsLargeObject
;
private
Column
rowIdColumn
;
private
Column
rowIdColumn
;
private
final
TransactionStore
store
;
/**
/**
* True if one thread ever was waiting to lock this table. This is to avoid
* True if one thread ever was waiting to lock this table. This is to avoid
* calling notifyAll if no session was ever waiting to lock this table. If
* calling notifyAll if no session was ever waiting to lock this table. If
...
@@ -68,11 +68,10 @@ public class MVTable extends TableBase {
...
@@ -68,11 +68,10 @@ public class MVTable extends TableBase {
*/
*/
private
boolean
waitForLock
;
private
boolean
waitForLock
;
public
MVTable
(
CreateTableData
data
,
String
storeName
,
Transaction
Store
store
)
{
public
MVTable
(
CreateTableData
data
,
MVTableEngine
.
Store
store
)
{
super
(
data
);
super
(
data
);
nextAnalyze
=
database
.
getSettings
().
analyzeAuto
;
nextAnalyze
=
database
.
getSettings
().
analyzeAuto
;
this
.
storeName
=
storeName
;
this
.
store
=
store
.
getTransactionStore
();
this
.
store
=
store
;
this
.
isHidden
=
data
.
isHidden
;
this
.
isHidden
=
data
.
isHidden
;
for
(
Column
col
:
getColumns
())
{
for
(
Column
col
:
getColumns
())
{
if
(
DataType
.
isLargeObject
(
col
.
getType
()))
{
if
(
DataType
.
isLargeObject
(
col
.
getType
()))
{
...
@@ -97,6 +96,10 @@ public class MVTable extends TableBase {
...
@@ -97,6 +96,10 @@ public class MVTable extends TableBase {
indexes
.
add
(
primaryIndex
);
indexes
.
add
(
primaryIndex
);
}
}
public
String
getMapName
()
{
return
primaryIndex
.
getMapName
();
}
@Override
@Override
public
void
lock
(
Session
session
,
boolean
exclusive
,
boolean
force
)
{
public
void
lock
(
Session
session
,
boolean
exclusive
,
boolean
force
)
{
int
lockMode
=
database
.
getLockMode
();
int
lockMode
=
database
.
getLockMode
();
...
@@ -354,7 +357,7 @@ public class MVTable extends TableBase {
...
@@ -354,7 +357,7 @@ public class MVTable extends TableBase {
@Override
@Override
public
void
close
(
Session
session
)
{
public
void
close
(
Session
session
)
{
MVTableEngine
.
closeTable
(
storeName
,
this
);
// ignore
}
}
/**
/**
...
@@ -675,7 +678,7 @@ public class MVTable extends TableBase {
...
@@ -675,7 +678,7 @@ public class MVTable extends TableBase {
// TODO need to commit/rollback the transaction
// TODO need to commit/rollback the transaction
return
store
.
begin
();
return
store
.
begin
();
}
}
return
session
.
getTransaction
(
store
);
return
session
.
getTransaction
();
}
}
@Override
@Override
...
...
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
3fcb3c2a
...
@@ -6,13 +6,13 @@
...
@@ -6,13 +6,13 @@
*/
*/
package
org
.
h2
.
mvstore
.
db
;
package
org
.
h2
.
mvstore
.
db
;
import
java.io.IOException
;
import
java.nio.channels.FileChannel
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.WeakHashMap
;
import
org.h2.api.TableEngine
;
import
org.h2.api.TableEngine
;
import
org.h2.command.ddl.CreateTableData
;
import
org.h2.command.ddl.CreateTableData
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Database
;
import
org.h2.engine.Database
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
...
@@ -25,45 +25,18 @@ import org.h2.util.New;
...
@@ -25,45 +25,18 @@ import org.h2.util.New;
*/
*/
public
class
MVTableEngine
implements
TableEngine
{
public
class
MVTableEngine
implements
TableEngine
{
static
final
Map
<
String
,
Store
>
STORES
=
new
WeakHashMap
<
String
,
Store
>();
/**
* Flush all changes.
*
* @param db the database
*/
public
static
void
flush
(
Database
db
)
{
String
storeName
=
db
.
getDatabasePath
();
if
(
storeName
==
null
)
{
return
;
}
synchronized
(
STORES
)
{
Store
store
=
STORES
.
get
(
storeName
);
if
(
store
==
null
)
{
return
;
}
store
(
store
.
getStore
());
}
}
public
static
Collection
<
Store
>
getStores
()
{
return
STORES
.
values
();
}
@Override
@Override
public
TableBase
createTable
(
CreateTableData
data
)
{
public
TableBase
createTable
(
CreateTableData
data
)
{
Database
db
=
data
.
session
.
getDatabase
();
Database
db
=
data
.
session
.
getDatabase
();
Store
store
=
db
.
getMvStore
();
if
(
store
==
null
)
{
byte
[]
key
=
db
.
getFilePasswordHash
();
byte
[]
key
=
db
.
getFilePasswordHash
();
String
storeName
=
db
.
getDatabasePath
();
String
dbPath
=
db
.
getDatabasePath
();
MVStore
.
Builder
builder
=
new
MVStore
.
Builder
();
MVStore
.
Builder
builder
=
new
MVStore
.
Builder
();
Store
store
;
if
(
dbPath
==
null
)
{
if
(
storeName
==
null
)
{
store
=
new
Store
(
db
,
builder
.
open
());
store
=
new
Store
(
db
,
builder
.
open
());
}
else
{
}
else
{
synchronized
(
STORES
)
{
builder
.
fileName
(
dbPath
+
Constants
.
SUFFIX_MV_FILE
);
store
=
STORES
.
get
(
storeName
);
if
(
store
==
null
)
{
builder
.
fileName
(
storeName
+
Constants
.
SUFFIX_MV_FILE
);
if
(
db
.
isReadOnly
())
{
if
(
db
.
isReadOnly
())
{
builder
.
readOnly
();
builder
.
readOnly
();
}
}
...
@@ -75,52 +48,15 @@ public class MVTableEngine implements TableEngine {
...
@@ -75,52 +48,15 @@ public class MVTableEngine implements TableEngine {
builder
.
encryptionKey
(
password
);
builder
.
encryptionKey
(
password
);
}
}
store
=
new
Store
(
db
,
builder
.
open
());
store
=
new
Store
(
db
,
builder
.
open
());
STORES
.
put
(
storeName
,
store
);
}
else
if
(
store
.
db
!=
db
)
{
throw
DbException
.
get
(
ErrorCode
.
DATABASE_ALREADY_OPEN_1
,
storeName
);
}
}
db
.
setMvStore
(
store
);
}
}
}
MVTable
table
=
new
MVTable
(
data
,
store
);
MVTable
table
=
new
MVTable
(
data
,
storeName
,
store
.
getTransactionStore
());
store
.
openTables
.
add
(
table
);
store
.
openTables
.
add
(
table
);
table
.
init
(
data
.
session
);
table
.
init
(
data
.
session
);
return
table
;
return
table
;
}
}
/**
* Close the table, and close the store if there are no remaining open
* tables.
*
* @param storeName the store name
* @param table the table
*/
static
void
closeTable
(
String
storeName
,
MVTable
table
)
{
synchronized
(
STORES
)
{
Store
store
=
STORES
.
get
(
storeName
);
if
(
store
!=
null
)
{
store
.
openTables
.
remove
(
table
);
if
(
store
.
openTables
.
size
()
==
0
)
{
store
(
store
.
getStore
());
store
.
getStore
().
close
();
STORES
.
remove
(
storeName
);
}
}
}
}
/**
* Store the data if needed.
*
* @param store the store
*/
static
void
store
(
MVStore
store
)
{
if
(!
store
.
isReadOnly
())
{
store
.
commit
();
store
.
compact
(
50
);
store
.
store
();
}
}
/**
/**
* A store with open tables.
* A store with open tables.
*/
*/
...
@@ -161,6 +97,39 @@ public class MVTableEngine implements TableEngine {
...
@@ -161,6 +97,39 @@ public class MVTableEngine implements TableEngine {
return
transactionStore
;
return
transactionStore
;
}
}
public
List
<
MVTable
>
getTables
()
{
return
openTables
;
}
public
void
store
()
{
if
(!
store
.
isReadOnly
())
{
store
.
commit
();
store
.
compact
(
50
);
store
.
store
();
}
}
public
void
closeImmediately
()
{
if
(
store
.
isClosed
())
{
return
;
}
FileChannel
f
=
store
.
getFile
();
if
(
f
!=
null
)
{
try
{
f
.
close
();
}
catch
(
IOException
e
)
{
throw
DbException
.
convertIOException
(
e
,
"Closing file"
);
}
}
}
public
void
close
()
{
if
(!
store
.
isReadOnly
())
{
store
.
store
();
}
store
.
close
();
}
}
}
}
}
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
3fcb3c2a
...
@@ -8,9 +8,11 @@ package org.h2.mvstore.db;
...
@@ -8,9 +8,11 @@ package org.h2.mvstore.db;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
org.h2.mvstore.Cursor
;
import
org.h2.mvstore.Cursor
;
import
org.h2.mvstore.DataUtils
;
import
org.h2.mvstore.DataUtils
;
...
@@ -28,7 +30,7 @@ public class TransactionStore {
...
@@ -28,7 +30,7 @@ public class TransactionStore {
private
static
final
String
LAST_TRANSACTION_ID
=
"lastTransactionId"
;
private
static
final
String
LAST_TRANSACTION_ID
=
"lastTransactionId"
;
// TODO should not be hardcoded
// TODO should not be hard
-
coded
private
static
final
int
MAX_UNSAVED_PAGES
=
4
*
1024
;
private
static
final
int
MAX_UNSAVED_PAGES
=
4
*
1024
;
/**
/**
...
@@ -246,21 +248,10 @@ public class TransactionStore {
...
@@ -246,21 +248,10 @@ public class TransactionStore {
endTransaction
(
t
);
endTransaction
(
t
);
}
}
/**
* Roll a transaction back.
*
* @param t the transaction
* @param maxLogId the last log id
*/
void
rollback
(
Transaction
t
,
long
maxLogId
)
{
rollbackTo
(
t
,
maxLogId
,
0
);
endTransaction
(
t
);
}
boolean
isTransactionOpen
(
long
transactionId
)
{
boolean
isTransactionOpen
(
long
transactionId
)
{
//
if (transactionId < firstOpenTransaction) {
if
(
transactionId
<
firstOpenTransaction
)
{
//
return false;
return
false
;
//
}
}
if
(
firstOpenTransaction
==
-
1
)
{
if
(
firstOpenTransaction
==
-
1
)
{
if
(
undoLog
.
size
()
==
0
)
{
if
(
undoLog
.
size
()
==
0
)
{
return
false
;
return
false
;
...
@@ -276,7 +267,7 @@ public class TransactionStore {
...
@@ -276,7 +267,7 @@ public class TransactionStore {
return
key
!=
null
&&
key
[
0
]
==
transactionId
;
return
key
!=
null
&&
key
[
0
]
==
transactionId
;
}
}
private
void
endTransaction
(
Transaction
t
)
{
void
endTransaction
(
Transaction
t
)
{
if
(
t
.
getStatus
()
==
Transaction
.
STATUS_PREPARED
)
{
if
(
t
.
getStatus
()
==
Transaction
.
STATUS_PREPARED
)
{
preparedTransactions
.
remove
(
t
.
getId
());
preparedTransactions
.
remove
(
t
.
getId
());
}
}
...
@@ -299,6 +290,7 @@ public class TransactionStore {
...
@@ -299,6 +290,7 @@ public class TransactionStore {
Object
[]
op
=
undoLog
.
get
(
new
long
[]
{
Object
[]
op
=
undoLog
.
get
(
new
long
[]
{
t
.
getId
(),
logId
});
t
.
getId
(),
logId
});
int
mapId
=
((
Integer
)
op
[
1
]).
intValue
();
int
mapId
=
((
Integer
)
op
[
1
]).
intValue
();
// TODO open map by id if possible
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
...
@@ -316,6 +308,21 @@ public class TransactionStore {
...
@@ -316,6 +308,21 @@ public class TransactionStore {
}
}
}
}
HashSet
<
String
>
getChangedMaps
(
Transaction
t
,
long
maxLogId
,
long
toLogId
)
{
HashSet
<
String
>
set
=
New
.
hashSet
();
for
(
long
logId
=
maxLogId
-
1
;
logId
>=
toLogId
;
logId
--)
{
Object
[]
op
=
undoLog
.
get
(
new
long
[]
{
t
.
getId
(),
logId
});
int
mapId
=
((
Integer
)
op
[
1
]).
intValue
();
// TODO open map by id if possible
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
set
.
add
(
mapName
);
}
return
set
;
}
/**
/**
* A transaction.
* A transaction.
*/
*/
...
@@ -451,18 +458,6 @@ public class TransactionStore {
...
@@ -451,18 +458,6 @@ public class TransactionStore {
return
new
TransactionMap
<
K
,
V
>(
this
,
name
,
keyType
,
valueType
);
return
new
TransactionMap
<
K
,
V
>(
this
,
name
,
keyType
,
valueType
);
}
}
/**
* Roll back to the given savepoint. This is only allowed if the
* transaction is open.
*
* @param savepointId the savepoint id
*/
public
void
rollbackToSavepoint
(
long
savepointId
)
{
checkOpen
();
store
.
rollbackTo
(
this
,
this
.
logId
,
savepointId
);
this
.
logId
=
savepointId
;
}
/**
/**
* Prepare the transaction. Afterwards, the transaction can only be
* Prepare the transaction. Afterwards, the transaction can only be
* committed or rolled back.
* committed or rolled back.
...
@@ -477,18 +472,41 @@ public class TransactionStore {
...
@@ -477,18 +472,41 @@ public class TransactionStore {
* Commit the transaction. Afterwards, this transaction is closed.
* Commit the transaction. Afterwards, this transaction is closed.
*/
*/
public
void
commit
()
{
public
void
commit
()
{
if
(
status
!=
STATUS_CLOSED
)
{
checkNotClosed
();
store
.
commit
(
this
,
logId
);
store
.
commit
(
this
,
logId
);
}
}
/**
* Roll back to the given savepoint. This is only allowed if the
* transaction is open.
*
* @param savepointId the savepoint id
*/
public
void
rollbackToSavepoint
(
long
savepointId
)
{
checkOpen
();
store
.
rollbackTo
(
this
,
logId
,
savepointId
);
logId
=
savepointId
;
}
}
/**
/**
* Roll the transaction back. Afterwards, this transaction is closed.
* Roll the transaction back. Afterwards, this transaction is closed.
*/
*/
public
void
rollback
()
{
public
void
rollback
()
{
if
(
status
!=
STATUS_CLOSED
)
{
checkNotClosed
();
store
.
rollback
(
this
,
logId
);
store
.
rollbackTo
(
this
,
logId
,
0
);
store
.
endTransaction
(
this
);
}
}
/**
* Get the set of changed maps starting at the given savepoint up to
* now.
*
* @param savepointId the savepoint id, 0 meaning the beginning of the
* transaction
* @return the set of changed maps
*/
public
Set
<
String
>
getChangedMaps
(
long
savepointId
)
{
return
store
.
getChangedMaps
(
this
,
logId
,
savepointId
);
}
}
/**
/**
...
@@ -500,8 +518,13 @@ public class TransactionStore {
...
@@ -500,8 +518,13 @@ public class TransactionStore {
}
}
}
}
public
long
getCurrentVersion
()
{
/**
return
store
.
store
.
getCurrentVersion
();
* Check whether this transaction is open or prepared.
*/
void
checkNotClosed
()
{
if
(
status
==
STATUS_CLOSED
)
{
throw
DataUtils
.
newIllegalStateException
(
"Transaction is closed"
);
}
}
}
}
}
...
...
h2/src/main/org/h2/mvstore/db/ValueDataType.java
浏览文件 @
3fcb3c2a
...
@@ -618,14 +618,12 @@ public class ValueDataType implements DataType {
...
@@ -618,14 +618,12 @@ public class ValueDataType implements DataType {
}
}
if
(
smallLen
==
-
2
)
{
if
(
smallLen
==
-
2
)
{
String
filename
=
readString
(
buff
);
String
filename
=
readString
(
buff
);
ValueLob
lob
=
ValueLob
.
openUnlinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
,
filename
);
return
ValueLob
.
openUnlinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
,
filename
);
return
lob
;
}
}
else
{
ValueLob
lob
=
ValueLob
.
openLinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
);
ValueLob
lob
=
ValueLob
.
openLinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
);
return
lob
;
return
lob
;
}
}
}
}
}
case
Value
.
ARRAY
:
{
case
Value
.
ARRAY
:
{
int
len
=
readVarInt
(
buff
);
int
len
=
readVarInt
(
buff
);
Value
[]
list
=
new
Value
[
len
];
Value
[]
list
=
new
Value
[
len
];
...
...
h2/src/main/org/h2/server/TcpServerThread.java
浏览文件 @
3fcb3c2a
...
@@ -398,9 +398,9 @@ public class TcpServerThread implements Runnable {
...
@@ -398,9 +398,9 @@ public class TcpServerThread implements Runnable {
transfer
.
writeInt
(
SessionRemote
.
STATUS_OK
).
flush
();
transfer
.
writeInt
(
SessionRemote
.
STATUS_OK
).
flush
();
break
;
break
;
}
}
case
SessionRemote
.
SESSION_
UNDO_LOG_POS
:
{
case
SessionRemote
.
SESSION_
HAS_PENDING_TRANSACTION
:
{
transfer
.
writeInt
(
SessionRemote
.
STATUS_OK
).
transfer
.
writeInt
(
SessionRemote
.
STATUS_OK
).
writeInt
(
session
.
getUndoLogPos
()
).
flush
();
writeInt
(
session
.
hasPendingTransaction
()
?
1
:
0
).
flush
();
break
;
break
;
}
}
case
SessionRemote
.
LOB_READ
:
{
case
SessionRemote
.
LOB_READ
:
{
...
...
h2/src/main/org/h2/store/Data.java
浏览文件 @
3fcb3c2a
...
@@ -808,12 +808,9 @@ public class Data {
...
@@ -808,12 +808,9 @@ public class Data {
}
}
if
(
smallLen
==
-
2
)
{
if
(
smallLen
==
-
2
)
{
String
filename
=
readString
();
String
filename
=
readString
();
ValueLob
lob
=
ValueLob
.
openUnlinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
,
filename
);
return
ValueLob
.
openUnlinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
,
filename
);
return
lob
;
}
else
{
ValueLob
lob
=
ValueLob
.
openLinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
);
return
lob
;
}
}
return
ValueLob
.
openLinked
(
type
,
handler
,
tableId
,
objectId
,
precision
,
compression
);
}
}
}
}
case
Value
.
ARRAY
:
{
case
Value
.
ARRAY
:
{
...
...
h2/src/main/org/h2/store/LobStorageFrontend.java
浏览文件 @
3fcb3c2a
...
@@ -34,7 +34,7 @@ public class LobStorageFrontend implements LobStorageInterface {
...
@@ -34,7 +34,7 @@ public class LobStorageFrontend implements LobStorageInterface {
*/
*/
@Override
@Override
public
void
removeLob
(
long
lob
)
{
public
void
removeLob
(
long
lob
)
{
// TODO
ideally,
this should not be called at all, but that's a refactoring for another day
// TODO this should not be called at all, but that's a refactoring for another day
}
}
/**
/**
...
@@ -64,7 +64,7 @@ public class LobStorageFrontend implements LobStorageInterface {
...
@@ -64,7 +64,7 @@ public class LobStorageFrontend implements LobStorageInterface {
*/
*/
@Override
@Override
public
ValueLobDb
copyLob
(
int
type
,
long
oldLobId
,
int
tableId
,
long
length
)
{
public
ValueLobDb
copyLob
(
int
type
,
long
oldLobId
,
int
tableId
,
long
length
)
{
// TODO
ideally,
this should not be called at all, but that's a refactoring for another day
// TODO this should not be called at all, but that's a refactoring for another day
// this should never be called
// this should never be called
throw
new
UnsupportedOperationException
();
throw
new
UnsupportedOperationException
();
}
}
...
...
h2/src/main/org/h2/table/Table.java
浏览文件 @
3fcb3c2a
...
@@ -426,7 +426,7 @@ public abstract class Table extends SchemaObjectBase {
...
@@ -426,7 +426,7 @@ public abstract class Table extends SchemaObjectBase {
*/
*/
public
void
updateRows
(
Prepared
prepared
,
Session
session
,
RowList
rows
)
{
public
void
updateRows
(
Prepared
prepared
,
Session
session
,
RowList
rows
)
{
// in case we need to undo the update
// in case we need to undo the update
int
rollback
=
session
.
getUndoLogPos
();
Session
.
Savepoint
rollback
=
session
.
setSavepoint
();
// remove the old rows
// remove the old rows
int
rowScanCount
=
0
;
int
rowScanCount
=
0
;
for
(
rows
.
reset
();
rows
.
hasNext
();)
{
for
(
rows
.
reset
();
rows
.
hasNext
();)
{
...
...
h2/src/main/org/h2/util/SourceCompiler.java
浏览文件 @
3fcb3c2a
...
@@ -274,9 +274,9 @@ public class SourceCompiler {
...
@@ -274,9 +274,9 @@ public class SourceCompiler {
static
{
static
{
Object
tmpLoader
=
null
;
Object
tmpLoader
=
null
;
Throwable
tmpInit
f
ailException
=
null
;
Throwable
tmpInit
F
ailException
=
null
;
try
{
try
{
// create an instance of ImportCustomi
s
er
// create an instance of ImportCustomi
z
er
Class
<?>
importCustomizerClass
=
Class
.
forName
(
"org.codehaus.groovy.control.customizers.ImportCustomizer"
);
Class
<?>
importCustomizerClass
=
Class
.
forName
(
"org.codehaus.groovy.control.customizers.ImportCustomizer"
);
Object
importCustomizer
=
Utils
.
newInstance
(
"org.codehaus.groovy.control.customizers.ImportCustomizer"
);
Object
importCustomizer
=
Utils
.
newInstance
(
"org.codehaus.groovy.control.customizers.ImportCustomizer"
);
// Call the method ImportCustomizer#addImports(String[])
// Call the method ImportCustomizer#addImports(String[])
...
@@ -293,10 +293,10 @@ public class SourceCompiler {
...
@@ -293,10 +293,10 @@ public class SourceCompiler {
ClassLoader
parent
=
GroovyCompiler
.
class
.
getClassLoader
();
ClassLoader
parent
=
GroovyCompiler
.
class
.
getClassLoader
();
tmpLoader
=
Utils
.
newInstance
(
"groovy.lang.GroovyClassLoader"
,
parent
,
configuration
);
tmpLoader
=
Utils
.
newInstance
(
"groovy.lang.GroovyClassLoader"
,
parent
,
configuration
);
}
catch
(
Exception
ex
)
{
}
catch
(
Exception
ex
)
{
tmpInit
f
ailException
=
ex
;
tmpInit
F
ailException
=
ex
;
}
}
LOADER
=
tmpLoader
;
LOADER
=
tmpLoader
;
INIT_FAIL_EXCEPTION
=
tmpInit
f
ailException
;
INIT_FAIL_EXCEPTION
=
tmpInit
F
ailException
;
}
}
public
static
Class
<?>
parseClass
(
String
source
,
String
packageAndClassName
)
{
public
static
Class
<?>
parseClass
(
String
source
,
String
packageAndClassName
)
{
...
...
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
3fcb3c2a
...
@@ -12,6 +12,7 @@ import java.util.Iterator;
...
@@ -12,6 +12,7 @@ import java.util.Iterator;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Random
;
import
java.util.Random
;
import
java.util.TreeMap
;
import
java.util.TreeMap
;
import
org.h2.mvstore.Cursor
;
import
org.h2.mvstore.Cursor
;
import
org.h2.mvstore.MVMap
;
import
org.h2.mvstore.MVMap
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.MVStore
;
...
@@ -122,7 +123,7 @@ public class TestMVStore extends TestBase {
...
@@ -122,7 +123,7 @@ public class TestMVStore extends TestBase {
}
}
private
void
testWriteBuffer
()
throws
IOException
{
private
void
testWriteBuffer
()
throws
IOException
{
String
fileName
=
getBaseDir
()
+
"/test
AutoStor
eBuffer.h3"
;
String
fileName
=
getBaseDir
()
+
"/test
Writ
eBuffer.h3"
;
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
MVStore
s
;
MVStore
s
;
MVMap
<
Integer
,
byte
[]>
m
;
MVMap
<
Integer
,
byte
[]>
m
;
...
@@ -167,10 +168,24 @@ public class TestMVStore extends TestBase {
...
@@ -167,10 +168,24 @@ public class TestMVStore extends TestBase {
}
}
private
void
testWriteDelay
()
throws
InterruptedException
{
private
void
testWriteDelay
()
throws
InterruptedException
{
String
fileName
=
getBaseDir
()
+
"/testUndoTempStore.h3"
;
String
fileName
=
getBaseDir
()
+
"/testWriteDelay.h3"
;
FileUtils
.
delete
(
fileName
);
MVStore
s
;
MVStore
s
;
MVMap
<
Integer
,
String
>
m
;
MVMap
<
Integer
,
String
>
m
;
FileUtils
.
delete
(
fileName
);
s
=
new
MVStore
.
Builder
().
writeDelay
(
0
).
fileName
(
fileName
).
open
();
m
=
s
.
openMap
(
"data"
);
m
.
put
(
1
,
"1"
);
s
.
commit
();
s
.
close
();
s
=
new
MVStore
.
Builder
().
writeDelay
(
0
).
fileName
(
fileName
).
open
();
m
=
s
.
openMap
(
"data"
);
assertEquals
(
1
,
m
.
size
());
s
.
close
();
FileUtils
.
delete
(
fileName
);
s
=
new
MVStore
.
Builder
().
s
=
new
MVStore
.
Builder
().
writeDelay
(
1
).
writeDelay
(
1
).
fileName
(
fileName
).
fileName
(
fileName
).
...
@@ -468,6 +483,16 @@ public class TestMVStore extends TestBase {
...
@@ -468,6 +483,16 @@ public class TestMVStore extends TestBase {
for
(
int
i
=
0
;
i
<
100
;
i
+=
2
)
{
for
(
int
i
=
0
;
i
<
100
;
i
+=
2
)
{
map
.
put
(
i
,
10
*
i
);
map
.
put
(
i
,
10
*
i
);
}
}
Cursor
<
Integer
>
c
=
map
.
keyIterator
(
50
);
// skip must reset the root of the cursor
c
.
skip
(
10
);
for
(
int
i
=
70
;
i
<
100
;
i
+=
2
)
{
assertTrue
(
c
.
hasNext
());
assertEquals
(
i
,
c
.
next
().
intValue
());
}
assertFalse
(
c
.
hasNext
());
for
(
int
i
=
-
1
;
i
<
100
;
i
++)
{
for
(
int
i
=
-
1
;
i
<
100
;
i
++)
{
long
index
=
map
.
getKeyIndex
(
i
);
long
index
=
map
.
getKeyIndex
(
i
);
if
(
i
<
0
||
(
i
%
2
)
!=
0
)
{
if
(
i
<
0
||
(
i
%
2
)
!=
0
)
{
...
@@ -485,7 +510,7 @@ public class TestMVStore extends TestBase {
...
@@ -485,7 +510,7 @@ public class TestMVStore extends TestBase {
}
}
}
}
// skip
// skip
Cursor
<
Integer
>
c
=
map
.
keyIterator
(
0
);
c
=
map
.
keyIterator
(
0
);
assertTrue
(
c
.
hasNext
());
assertTrue
(
c
.
hasNext
());
assertEquals
(
0
,
c
.
next
().
intValue
());
assertEquals
(
0
,
c
.
next
().
intValue
());
c
.
skip
(
0
);
c
.
skip
(
0
);
...
@@ -513,8 +538,10 @@ public class TestMVStore extends TestBase {
...
@@ -513,8 +538,10 @@ public class TestMVStore extends TestBase {
MVMap
<
Integer
,
Integer
>
map
=
s
.
openMap
(
"test"
);
MVMap
<
Integer
,
Integer
>
map
=
s
.
openMap
(
"test"
);
map
.
put
(
10
,
100
);
map
.
put
(
10
,
100
);
map
.
put
(
20
,
200
);
map
.
put
(
20
,
200
);
assertEquals
(
10
,
map
.
firstKey
().
intValue
());
assertEquals
(
10
,
map
.
firstKey
().
intValue
());
assertEquals
(
20
,
map
.
lastKey
().
intValue
());
assertEquals
(
20
,
map
.
lastKey
().
intValue
());
assertEquals
(
20
,
map
.
ceilingKey
(
15
).
intValue
());
assertEquals
(
20
,
map
.
ceilingKey
(
15
).
intValue
());
assertEquals
(
20
,
map
.
ceilingKey
(
20
).
intValue
());
assertEquals
(
20
,
map
.
ceilingKey
(
20
).
intValue
());
assertEquals
(
10
,
map
.
floorKey
(
15
).
intValue
());
assertEquals
(
10
,
map
.
floorKey
(
15
).
intValue
());
...
@@ -522,6 +549,12 @@ public class TestMVStore extends TestBase {
...
@@ -522,6 +549,12 @@ public class TestMVStore extends TestBase {
assertEquals
(
20
,
map
.
higherKey
(
10
).
intValue
());
assertEquals
(
20
,
map
.
higherKey
(
10
).
intValue
());
assertEquals
(
10
,
map
.
lowerKey
(
20
).
intValue
());
assertEquals
(
10
,
map
.
lowerKey
(
20
).
intValue
());
final
MVMap
<
Integer
,
Integer
>
m
=
map
;
assertEquals
(
10
,
m
.
ceilingKey
(
null
).
intValue
());
assertEquals
(
10
,
m
.
higherKey
(
null
).
intValue
());
assertNull
(
m
.
lowerKey
(
null
));
assertNull
(
m
.
floorKey
(
null
));
for
(
int
i
=
3
;
i
<
20
;
i
++)
{
for
(
int
i
=
3
;
i
<
20
;
i
++)
{
s
=
openStore
(
null
);
s
=
openStore
(
null
);
s
.
setPageSize
(
4
);
s
.
setPageSize
(
4
);
...
...
h2/src/test/org/h2/test/store/TestMVTableEngine.java
浏览文件 @
3fcb3c2a
...
@@ -14,11 +14,13 @@ import java.sql.DriverManager;
...
@@ -14,11 +14,13 @@ import java.sql.DriverManager;
import
java.sql.PreparedStatement
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Savepoint
;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
import
org.h2.mvstore.db.MVTableEngine
;
import
org.h2.engine.Database
;
import
org.h2.jdbc.JdbcConnection
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
import
org.h2.util.Task
;
import
org.h2.util.Task
;
...
@@ -40,6 +42,7 @@ public class TestMVTableEngine extends TestBase {
...
@@ -40,6 +42,7 @@ public class TestMVTableEngine extends TestBase {
@Override
@Override
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
// testSpeed();
// testSpeed();
testAutoCommit
();
testReopen
();
testReopen
();
testBlob
();
testBlob
();
testExclusiveLock
();
testExclusiveLock
();
...
@@ -58,7 +61,7 @@ public class TestMVTableEngine extends TestBase {
...
@@ -58,7 +61,7 @@ public class TestMVTableEngine extends TestBase {
dbName
+=
";LOCK_MODE=0"
;
dbName
+=
";LOCK_MODE=0"
;
// dbName += ";LOG=0";
// dbName += ";LOG=0";
testSpeed
(
dbName
);
testSpeed
(
dbName
);
int
tes
;
int
tes
t
;
//Profiler prof = new Profiler().startCollecting();
//Profiler prof = new Profiler().startCollecting();
dbName
=
"mvstore"
+
dbName
=
"mvstore"
+
";DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine"
;
";DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine"
;
...
@@ -120,6 +123,37 @@ int tes;
...
@@ -120,6 +123,37 @@ int tes;
System
.
out
.
println
((
System
.
currentTimeMillis
()
-
time
)
+
" "
+
dbName
+
" after"
);
System
.
out
.
println
((
System
.
currentTimeMillis
()
-
time
)
+
" "
+
dbName
+
" after"
);
}
}
private
void
testAutoCommit
()
throws
SQLException
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
Connection
conn
;
Statement
stat
;
ResultSet
rs
;
conn
=
getConnection
(
"mvstore"
);
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id int primary key, name varchar) "
+
"engine \"org.h2.mvstore.db.MVTableEngine\""
);
conn
.
setAutoCommit
(
false
);
stat
.
execute
(
"insert into test values(1, 'Hello')"
);
stat
.
execute
(
"insert into test values(2, 'World')"
);
rs
=
stat
.
executeQuery
(
"select count(*) from test"
);
rs
.
next
();
assertEquals
(
2
,
rs
.
getInt
(
1
));
conn
.
rollback
();
rs
=
stat
.
executeQuery
(
"select count(*) from test"
);
rs
.
next
();
assertEquals
(
0
,
rs
.
getInt
(
1
));
stat
.
execute
(
"insert into test values(1, 'Hello')"
);
Savepoint
sp
=
conn
.
setSavepoint
();
stat
.
execute
(
"insert into test values(2, 'World')"
);
conn
.
rollback
(
sp
);
rs
=
stat
.
executeQuery
(
"select count(*) from test"
);
rs
.
next
();
assertEquals
(
1
,
rs
.
getInt
(
1
));
conn
.
close
();
}
private
void
testReopen
()
throws
SQLException
{
private
void
testReopen
()
throws
SQLException
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
Connection
conn
;
Connection
conn
;
...
@@ -220,9 +254,8 @@ int tes;
...
@@ -220,9 +254,8 @@ int tes;
conn
.
close
();
conn
.
close
();
FileUtils
.
setReadOnly
(
getBaseDir
()
+
"/mvstore.h2.db"
);
FileUtils
.
setReadOnly
(
getBaseDir
()
+
"/mvstore.h2.db"
);
conn
=
getConnection
(
dbName
);
conn
=
getConnection
(
dbName
);
for
(
MVTableEngine
.
Store
s
:
MVTableEngine
.
getStores
())
{
Database
db
=
(
Database
)
((
JdbcConnection
)
conn
).
getSession
().
getDataHandler
();
assertTrue
(
s
.
getStore
().
isReadOnly
());
assertTrue
(
db
.
getMvStore
().
getStore
().
isReadOnly
());
}
conn
.
close
();
conn
.
close
();
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
}
}
...
@@ -236,9 +269,8 @@ int tes;
...
@@ -236,9 +269,8 @@ int tes;
long
maxSize
=
0
;
long
maxSize
=
0
;
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
conn
=
getConnection
(
dbName
);
conn
=
getConnection
(
dbName
);
for
(
MVTableEngine
.
Store
s
:
MVTableEngine
.
getStores
())
{
Database
db
=
(
Database
)
((
JdbcConnection
)
conn
).
getSession
().
getDataHandler
();
s
.
getStore
().
setRetentionTime
(
0
);
db
.
getMvStore
().
getStore
().
setRetentionTime
(
0
);
}
stat
=
conn
.
createStatement
();
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id int primary key, data varchar)"
);
stat
.
execute
(
"create table test(id int primary key, data varchar)"
);
stat
.
execute
(
"insert into test select x, space(1000) from system_range(1, 1000)"
);
stat
.
execute
(
"insert into test select x, space(1000) from system_range(1, 1000)"
);
...
...
h2/src/test/org/h2/test/store/TestTransactionStore.java
浏览文件 @
3fcb3c2a
...
@@ -15,6 +15,7 @@ import java.util.ArrayList;
...
@@ -15,6 +15,7 @@ import java.util.ArrayList;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Random
;
import
java.util.Random
;
import
java.util.TreeSet
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.db.TransactionStore
;
import
org.h2.mvstore.db.TransactionStore
;
...
@@ -41,6 +42,7 @@ public class TestTransactionStore extends TestBase {
...
@@ -41,6 +42,7 @@ public class TestTransactionStore extends TestBase {
@Override
@Override
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
FileUtils
.
createDirectories
(
getBaseDir
());
FileUtils
.
createDirectories
(
getBaseDir
());
testGetModifiedMaps
();
testKeyIterator
();
testKeyIterator
();
testMultiStatement
();
testMultiStatement
();
testTwoPhaseCommit
();
testTwoPhaseCommit
();
...
@@ -50,6 +52,42 @@ public class TestTransactionStore extends TestBase {
...
@@ -50,6 +52,42 @@ public class TestTransactionStore extends TestBase {
testCompareWithPostgreSQL
();
testCompareWithPostgreSQL
();
}
}
private
void
testGetModifiedMaps
()
{
MVStore
s
=
MVStore
.
open
(
null
);
TransactionStore
ts
=
new
TransactionStore
(
s
);
Transaction
tx
;
TransactionMap
<
String
,
String
>
m1
,
m2
,
m3
;
long
sp
;
TreeSet
<
String
>
changed
;
tx
=
ts
.
begin
();
m1
=
tx
.
openMap
(
"m1"
);
m2
=
tx
.
openMap
(
"m2"
);
m3
=
tx
.
openMap
(
"m3"
);
changed
=
new
TreeSet
<
String
>(
tx
.
getChangedMaps
(
0
));
assertEquals
(
0
,
changed
.
size
());
tx
.
commit
();
tx
=
ts
.
begin
();
m1
=
tx
.
openMap
(
"m1"
);
m2
=
tx
.
openMap
(
"m2"
);
m3
=
tx
.
openMap
(
"m3"
);
m1
.
put
(
"1"
,
"100"
);
sp
=
tx
.
setSavepoint
();
m2
.
put
(
"1"
,
"100"
);
m3
.
put
(
"1"
,
"100"
);
changed
=
new
TreeSet
<
String
>(
tx
.
getChangedMaps
(
sp
));
assertEquals
(
"[m2, m3]"
,
changed
.
toString
());
changed
=
new
TreeSet
<
String
>(
tx
.
getChangedMaps
(
0
));
assertEquals
(
"[m1, m2, m3]"
,
changed
.
toString
());
tx
.
rollbackToSavepoint
(
sp
);
changed
=
new
TreeSet
<
String
>(
tx
.
getChangedMaps
(
0
));
assertEquals
(
"[m1]"
,
changed
.
toString
());
tx
.
commit
();
s
.
close
();
}
private
void
testKeyIterator
()
{
private
void
testKeyIterator
()
{
MVStore
s
=
MVStore
.
open
(
null
);
MVStore
s
=
MVStore
.
open
(
null
);
TransactionStore
ts
=
new
TransactionStore
(
s
);
TransactionStore
ts
=
new
TransactionStore
(
s
);
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
3fcb3c2a
...
@@ -725,4 +725,5 @@ brown tweak pbkdf sharding ieee galois otterstrom sharded hruda argaul gaul
...
@@ -725,4 +725,5 @@ brown tweak pbkdf sharding ieee galois otterstrom sharded hruda argaul gaul
simo unpredictable overtakes conditionally decreases warned coupled spin
simo unpredictable overtakes conditionally decreases warned coupled spin
unsynchronized reality cores effort slice addleman koskela ville blocking seen
unsynchronized reality cores effort slice addleman koskela ville blocking seen
isam charindex removal getdate jesse fake covers covering cheaper adjacent spot
isam charindex removal getdate jesse fake covers covering cheaper adjacent spot
transition anthony goubard netherlands versioned orderable customizer cachable
customizers retains
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论