Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
a67837cb
提交
a67837cb
authored
15 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
New experimental page store.
上级
9d9ca196
master
noel-pr1
plus33-master
pr/267
stumc-Issue#576
version-1.1.x
version-1.4.198
version-1.4.197
version-1.4.196
version-1.4.195
version-1.4.194
version-1.4.193
version-1.4.192
version-1.4.191
version-1.4.190
version-1.4.188
version-1.4.187
version-1.4.186
version-1.4.185
version-1.4.184
version-1.4.183
version-1.4.182
version-1.4.181
version-1.4.178
version-1.4.177
version-1.3
version-1.2
version-1.1
version-1.0
无相关合并请求
隐藏空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
428 行增加
和
72 行删除
+428
-72
Database.java
h2/src/main/org/h2/engine/Database.java
+9
-0
PageBtreeIndex.java
h2/src/main/org/h2/index/PageBtreeIndex.java
+4
-0
PageData.java
h2/src/main/org/h2/index/PageData.java
+3
-1
PageDataLeaf.java
h2/src/main/org/h2/index/PageDataLeaf.java
+3
-2
PageDataNode.java
h2/src/main/org/h2/index/PageDataNode.java
+3
-2
PageScanCursor.java
h2/src/main/org/h2/index/PageScanCursor.java
+46
-10
PageScanIndex.java
h2/src/main/org/h2/index/PageScanIndex.java
+72
-6
ScanIndex.java
h2/src/main/org/h2/index/ScanIndex.java
+1
-1
InDoubtTransaction.java
h2/src/main/org/h2/log/InDoubtTransaction.java
+29
-8
LogSystem.java
h2/src/main/org/h2/log/LogSystem.java
+7
-1
PageFreeList.java
h2/src/main/org/h2/store/PageFreeList.java
+4
-0
PageInputStream.java
h2/src/main/org/h2/store/PageInputStream.java
+6
-2
PageLog.java
h2/src/main/org/h2/store/PageLog.java
+166
-10
PageOutputStream.java
h2/src/main/org/h2/store/PageOutputStream.java
+2
-2
PageStore.java
h2/src/main/org/h2/store/PageStore.java
+58
-25
PageStreamData.java
h2/src/main/org/h2/store/PageStreamData.java
+3
-1
PageStreamTrunk.java
h2/src/main/org/h2/store/PageStreamTrunk.java
+1
-1
Recover.java
h2/src/main/org/h2/tools/Recover.java
+11
-0
没有找到文件。
h2/src/main/org/h2/engine/Database.java
浏览文件 @
a67837cb
...
...
@@ -2366,4 +2366,13 @@ public class Database implements DataHandler {
return
true
;
}
/**
* Switch the database to read-only mode.
*
* @param readOnly the new value
*/
public
void
setReadOnly
(
boolean
readOnly
)
{
this
.
readOnly
=
readOnly
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageBtreeIndex.java
浏览文件 @
a67837cb
...
...
@@ -370,4 +370,8 @@ public class PageBtreeIndex extends BaseIndex {
return
rowsize
;
}
public
boolean
canFindNext
()
{
return
true
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageData.java
浏览文件 @
a67837cb
...
...
@@ -8,6 +8,7 @@ package org.h2.index;
import
java.sql.SQLException
;
import
org.h2.engine.Session
;
import
org.h2.result.Row
;
import
org.h2.store.DataPage
;
import
org.h2.store.Record
;
...
...
@@ -107,9 +108,10 @@ abstract class PageData extends Record {
/**
* Get a cursor.
*
* @param session the session
* @return the cursor
*/
abstract
Cursor
find
()
throws
SQLException
;
abstract
Cursor
find
(
Session
session
)
throws
SQLException
;
/**
* Get the key at this position.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageDataLeaf.java
浏览文件 @
a67837cb
...
...
@@ -8,6 +8,7 @@ package org.h2.index;
import
java.sql.SQLException
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Session
;
import
org.h2.message.Message
;
import
org.h2.result.Row
;
import
org.h2.store.DataPage
;
...
...
@@ -193,8 +194,8 @@ class PageDataLeaf extends PageData {
rows
=
newRows
;
}
Cursor
find
()
{
return
new
PageScanCursor
(
this
,
0
);
Cursor
find
(
Session
session
)
{
return
new
PageScanCursor
(
session
,
this
,
0
,
index
.
isMultiVersion
);
}
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageDataNode.java
浏览文件 @
a67837cb
...
...
@@ -8,6 +8,7 @@ package org.h2.index;
import
java.sql.SQLException
;
import
org.h2.engine.Session
;
import
org.h2.message.Message
;
import
org.h2.result.Row
;
import
org.h2.store.DataPage
;
...
...
@@ -110,9 +111,9 @@ class PageDataNode extends PageData {
}
}
Cursor
find
()
throws
SQLException
{
Cursor
find
(
Session
session
)
throws
SQLException
{
int
child
=
childPageIds
[
0
];
return
index
.
getPage
(
child
).
find
();
return
index
.
getPage
(
child
).
find
(
session
);
}
PageData
split
(
int
splitPoint
)
throws
SQLException
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageScanCursor.java
浏览文件 @
a67837cb
...
...
@@ -7,7 +7,10 @@
package
org
.
h2
.
index
;
import
java.sql.SQLException
;
import
java.util.Iterator
;
import
org.h2.engine.Session
;
import
org.h2.message.Message
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
...
...
@@ -17,12 +20,20 @@ import org.h2.result.SearchRow;
class
PageScanCursor
implements
Cursor
{
private
PageDataLeaf
current
;
private
int
i
nde
x
;
private
int
i
d
x
;
private
Row
row
;
private
final
boolean
multiVersion
;
private
final
Session
session
;
private
Iterator
<
Row
>
delta
;
PageScanCursor
(
PageDataLeaf
current
,
int
index
)
{
PageScanCursor
(
Session
session
,
PageDataLeaf
current
,
int
idx
,
boolean
multiVersion
)
{
this
.
current
=
current
;
this
.
index
=
index
;
this
.
idx
=
idx
;
this
.
multiVersion
=
multiVersion
;
this
.
session
=
session
;
if
(
multiVersion
)
{
delta
=
current
.
index
.
getDelta
();
}
}
public
Row
get
()
{
...
...
@@ -38,22 +49,47 @@ class PageScanCursor implements Cursor {
}
public
boolean
next
()
throws
SQLException
{
if
(
index
>=
current
.
getEntryCount
())
{
if
(!
multiVersion
)
{
return
nextRow
();
}
while
(
true
)
{
if
(
delta
!=
null
)
{
if
(!
delta
.
hasNext
())
{
delta
=
null
;
row
=
null
;
continue
;
}
row
=
delta
.
next
();
if
(!
row
.
getDeleted
()
||
row
.
getSessionId
()
==
session
.
getId
())
{
continue
;
}
}
else
{
nextRow
();
if
(
row
!=
null
&&
row
.
getSessionId
()
!=
0
&&
row
.
getSessionId
()
!=
session
.
getId
())
{
continue
;
}
}
break
;
}
return
row
!=
null
;
}
private
boolean
nextRow
()
throws
SQLException
{
if
(
idx
>=
current
.
getEntryCount
())
{
current
=
current
.
getNextPage
();
i
nde
x
=
0
;
i
d
x
=
0
;
if
(
current
==
null
)
{
row
=
null
;
return
false
;
}
}
row
=
current
.
getRowAt
(
i
nde
x
);
i
nde
x
++;
row
=
current
.
getRowAt
(
i
d
x
);
i
d
x
++;
return
true
;
}
public
boolean
previous
()
{
index
--;
int
todo
;
return
true
;
throw
Message
.
throwInternalError
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageScanIndex.java
浏览文件 @
a67837cb
...
...
@@ -7,10 +7,16 @@
package
org
.
h2
.
index
;
import
java.sql.SQLException
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Session
;
import
org.h2.log.UndoLogRecord
;
import
org.h2.message.Message
;
import
org.h2.message.TraceSystem
;
import
org.h2.result.Row
;
...
...
@@ -21,6 +27,7 @@ import org.h2.store.Record;
import
org.h2.table.Column
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.TableData
;
import
org.h2.util.New
;
import
org.h2.value.Value
;
import
org.h2.value.ValueLob
;
...
...
@@ -36,13 +43,17 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
private
final
int
headPos
;
private
int
lastKey
;
private
long
rowCount
;
private
HashSet
<
Row
>
delta
;
private
int
rowCountDiff
;
private
HashMap
<
Integer
,
Integer
>
sessionRowCount
;
public
PageScanIndex
(
TableData
table
,
int
id
,
IndexColumn
[]
columns
,
IndexType
indexType
,
int
headPos
,
Session
session
)
throws
SQLException
{
initBaseIndex
(
table
,
id
,
table
.
getName
()
+
"_TABLE_SCAN"
,
columns
,
indexType
);
int
test
;
// trace.setLevel(TraceSystem.DEBUG);
if
(
database
.
isMultiVersion
())
{
int
todoMvcc
;
sessionRowCount
=
New
.
hashMap
();
isMultiVersion
=
true
;
}
tableData
=
table
;
this
.
store
=
database
.
getPageStore
();
...
...
@@ -130,6 +141,16 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
store
.
updateRecord
(
newRoot
,
true
,
null
);
root
=
newRoot
;
}
if
(
database
.
isMultiVersion
())
{
if
(
delta
==
null
)
{
delta
=
New
.
hashSet
();
}
boolean
wasDeleted
=
delta
.
remove
(
row
);
if
(!
wasDeleted
)
{
delta
.
add
(
row
);
}
incrementRowCount
(
session
.
getId
(),
1
);
}
rowCount
++;
store
.
logAddOrRemoveRow
(
session
,
tableData
.
getId
(),
row
,
true
);
}
...
...
@@ -143,10 +164,6 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
PageData
getPage
(
int
id
)
throws
SQLException
{
Record
rec
=
store
.
getRecord
(
id
);
if
(
rec
!=
null
)
{
if
(
rec
instanceof
PageDataLeafOverflow
)
{
int
test
;
System
.
out
.
println
(
"stop"
);
}
return
(
PageData
)
rec
;
}
DataPage
data
=
store
.
readPage
(
id
);
...
...
@@ -177,7 +194,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
public
Cursor
find
(
Session
session
,
SearchRow
first
,
SearchRow
last
)
throws
SQLException
{
PageData
root
=
getPage
(
headPos
);
return
root
.
find
();
return
root
.
find
(
session
);
}
public
Cursor
findFirstOrLast
(
Session
session
,
boolean
first
)
throws
SQLException
{
...
...
@@ -220,6 +237,18 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
// lastKey--;
// }
}
if
(
database
.
isMultiVersion
())
{
// if storage is null, the delete flag is not yet set
row
.
setDeleted
(
true
);
if
(
delta
==
null
)
{
delta
=
New
.
hashSet
();
}
boolean
wasAdded
=
delta
.
remove
(
row
);
if
(!
wasAdded
)
{
delta
.
add
(
row
);
}
incrementRowCount
(
session
.
getId
(),
-
1
);
}
store
.
logAddOrRemoveRow
(
session
,
tableData
.
getId
(),
row
,
false
);
}
...
...
@@ -238,6 +267,9 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
if
(
tableData
.
getContainsLargeObject
()
&&
tableData
.
isPersistData
())
{
ValueLob
.
removeAllForTable
(
database
,
table
.
getId
());
}
if
(
database
.
isMultiVersion
())
{
sessionRowCount
.
clear
();
}
tableData
.
setRowCount
(
0
);
}
...
...
@@ -279,6 +311,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
public
long
getRowCount
(
Session
session
)
{
if
(
database
.
isMultiVersion
())
{
Integer
i
=
sessionRowCount
.
get
(
session
.
getId
());
long
count
=
i
==
null
?
0
:
i
.
intValue
();
count
+=
rowCount
;
count
-=
rowCountDiff
;
return
count
;
}
return
rowCount
;
}
...
...
@@ -301,4 +340,31 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
int
writeRowCount
;
}
Iterator
<
Row
>
getDelta
()
{
if
(
delta
==
null
)
{
List
<
Row
>
e
=
Collections
.
emptyList
();
return
e
.
iterator
();
}
return
delta
.
iterator
();
}
private
void
incrementRowCount
(
int
sessionId
,
int
count
)
{
if
(
database
.
isMultiVersion
())
{
Integer
id
=
sessionId
;
Integer
c
=
sessionRowCount
.
get
(
id
);
int
current
=
c
==
null
?
0
:
c
.
intValue
();
sessionRowCount
.
put
(
id
,
current
+
count
);
rowCountDiff
+=
count
;
}
}
public
void
commit
(
int
operation
,
Row
row
)
{
if
(
database
.
isMultiVersion
())
{
if
(
delta
!=
null
)
{
delta
.
remove
(
row
);
}
incrementRowCount
(
row
.
getSessionId
(),
operation
==
UndoLogRecord
.
DELETE
?
1
:
-
1
);
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/ScanIndex.java
浏览文件 @
a67837cb
...
...
@@ -280,7 +280,7 @@ public class ScanIndex extends BaseIndex implements RowIndex {
throw
Message
.
getUnsupportedException
(
"SCAN"
);
}
public
Iterator
<
Row
>
getDelta
()
{
Iterator
<
Row
>
getDelta
()
{
if
(
delta
==
null
)
{
List
<
Row
>
e
=
Collections
.
emptyList
();
return
e
.
iterator
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/log/InDoubtTransaction.java
浏览文件 @
a67837cb
...
...
@@ -9,6 +9,7 @@ package org.h2.log;
import
java.sql.SQLException
;
import
org.h2.message.Message
;
import
org.h2.store.PageStore
;
/**
* Represents an in-doubt transaction (a transaction in the prepare phase).
...
...
@@ -33,14 +34,26 @@ public class InDoubtTransaction {
// TODO 2-phase-commit: document sql statements and metadata table
private
LogFile
log
;
private
int
sessionId
;
private
int
pos
;
private
String
transaction
;
private
int
blocks
;
private
final
PageStore
store
;
private
final
LogFile
log
;
private
final
int
sessionId
;
private
final
int
pos
;
private
final
String
transaction
;
private
final
int
blocks
;
private
int
state
;
InDoubtTransaction
(
LogFile
log
,
int
sessionId
,
int
pos
,
String
transaction
,
int
blocks
)
{
/**
* Create a new in-doubt transaction info object.
*
* @param store the page store
* @param log the log file
* @param sessionId the session id
* @param pos the position
* @param transaction the transaction name
* @param blocks the number of blocks the 'prepare commit' entry occupies
*/
public
InDoubtTransaction
(
PageStore
store
,
LogFile
log
,
int
sessionId
,
int
pos
,
String
transaction
,
int
blocks
)
{
this
.
store
=
store
;
this
.
log
=
log
;
this
.
sessionId
=
sessionId
;
this
.
pos
=
pos
;
...
...
@@ -58,10 +71,18 @@ public class InDoubtTransaction {
public
void
setState
(
int
state
)
throws
SQLException
{
switch
(
state
)
{
case
COMMIT:
log
.
updatePreparedCommit
(
true
,
pos
,
sessionId
,
blocks
);
if
(
store
!=
null
)
{
store
.
setInDoubtTransactionState
(
sessionId
,
pos
,
true
);
}
else
{
log
.
updatePreparedCommit
(
true
,
pos
,
sessionId
,
blocks
);
}
break
;
case
ROLLBACK:
log
.
updatePreparedCommit
(
false
,
pos
,
sessionId
,
blocks
);
if
(
store
!=
null
)
{
store
.
setInDoubtTransactionState
(
sessionId
,
pos
,
false
);
}
else
{
log
.
updatePreparedCommit
(
false
,
pos
,
sessionId
,
blocks
);
}
break
;
default
:
Message
.
throwInternalError
(
"state="
+
state
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/log/LogSystem.java
浏览文件 @
a67837cb
...
...
@@ -410,7 +410,7 @@ public class LogSystem {
// this is potentially a commit, so
// don't roll back the action before it (currently)
setLastCommitForSession
(
sessionId
,
log
.
getId
(),
pos
);
state
.
inDoubtTransaction
=
new
InDoubtTransaction
(
log
,
sessionId
,
pos
,
transaction
,
blocks
);
state
.
inDoubtTransaction
=
new
InDoubtTransaction
(
null
,
log
,
sessionId
,
pos
,
transaction
,
blocks
);
}
/**
...
...
@@ -419,6 +419,9 @@ public class LogSystem {
* @return the list
*/
public
ObjectArray
<
InDoubtTransaction
>
getInDoubtTransactions
()
{
if
(
pageStore
!=
null
)
{
return
pageStore
.
getInDoubtTransactions
();
}
return
inDoubtTransactions
;
}
...
...
@@ -444,6 +447,9 @@ public class LogSystem {
return
;
}
synchronized
(
database
)
{
if
(
pageStore
!=
null
)
{
pageStore
.
prepareCommit
(
session
,
transaction
);
}
if
(
closed
)
{
return
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageFreeList.java
浏览文件 @
a67837cb
...
...
@@ -83,6 +83,10 @@ public class PageFreeList extends Record {
*/
void
free
(
int
pageId
)
throws
SQLException
{
full
=
false
;
int
test
;
if
(
pageId
-
getPos
()
<=
0
)
{
System
.
out
.
println
(
"stop!"
);
}
used
.
clear
(
pageId
-
getPos
());
store
.
updateRecord
(
this
,
true
,
data
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageInputStream.java
浏览文件 @
a67837cb
...
...
@@ -89,7 +89,7 @@ public class PageInputStream extends InputStream {
}
int
next
;
while
(
true
)
{
next
=
trunk
.
getNext
DataPage
();
next
=
trunk
.
getNext
PageData
();
if
(
dataPage
==
-
1
||
dataPage
==
next
)
{
if
(
next
!=
0
)
{
break
;
...
...
@@ -117,7 +117,7 @@ public class PageInputStream extends InputStream {
PageStreamTrunk
t
=
new
PageStreamTrunk
(
store
,
trunkPage
);
t
.
read
();
while
(
true
)
{
int
n
=
t
.
getNext
DataPage
();
int
n
=
t
.
getNext
PageData
();
if
(
n
==
-
1
)
{
break
;
}
...
...
@@ -130,4 +130,8 @@ public class PageInputStream extends InputStream {
}
}
int
getDataPage
()
{
return
data
.
getPos
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageLog.java
浏览文件 @
a67837cb
...
...
@@ -14,6 +14,7 @@ import java.io.IOException;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
org.h2.engine.Session
;
import
org.h2.log.InDoubtTransaction
;
import
org.h2.log.LogSystem
;
import
org.h2.log.SessionState
;
import
org.h2.message.Message
;
...
...
@@ -22,6 +23,8 @@ import org.h2.result.Row;
import
org.h2.util.BitField
;
import
org.h2.util.IntIntHashMap
;
import
org.h2.util.New
;
import
org.h2.util.ObjectArray
;
import
org.h2.util.StringUtils
;
import
org.h2.value.Value
;
/**
...
...
@@ -52,23 +55,35 @@ public class PageLog {
*/
public
static
final
int
COMMIT
=
2
;
/**
* A prepare commit entry for a session.
* Format: session id, transaction name length, transaction name (UTF-8).
*/
public
static
final
int
PREPARE_COMMIT
=
3
;
/**
* Roll back a prepared transaction.
* Format: session id.
*/
public
static
final
int
ROLLBACK
=
4
;
/**
* Add a record to a table.
* Format: session id, table id, row.
*/
public
static
final
int
ADD
=
3
;
public
static
final
int
ADD
=
5
;
/**
* Remove a record from a table.
* Format: session id, table id, row.
*/
public
static
final
int
REMOVE
=
4
;
public
static
final
int
REMOVE
=
6
;
/**
* Perform a checkpoint. The log id is incremented.
* Format: -
*/
public
static
final
int
CHECKPOINT
=
5
;
public
static
final
int
CHECKPOINT
=
7
;
/**
* The recovery stage to undo changes (re-apply the backup).
...
...
@@ -91,6 +106,7 @@ public class PageLog {
private
DataOutputStream
out
;
private
ByteArrayOutputStream
buffer
;
private
PageInputStream
pageIn
;
private
PageOutputStream
pageOut
;
private
DataInputStream
in
;
private
int
firstTrunkPage
;
...
...
@@ -164,7 +180,8 @@ public class PageLog {
in
.
allocateAllPages
();
return
;
}
in
=
new
DataInputStream
(
new
PageInputStream
(
store
,
firstTrunkPage
,
firstDataPage
));
pageIn
=
new
PageInputStream
(
store
,
firstTrunkPage
,
firstDataPage
);
in
=
new
DataInputStream
(
pageIn
);
int
logId
=
0
;
DataPage
data
=
store
.
createDataPage
();
try
{
...
...
@@ -200,6 +217,25 @@ public class PageLog {
}
}
}
}
else
if
(
x
==
PREPARE_COMMIT
)
{
int
sessionId
=
in
.
readInt
();
int
len
=
in
.
readInt
();
byte
[]
t
=
new
byte
[
len
];
in
.
readFully
(
t
);
String
transaction
=
StringUtils
.
utf8Decode
(
t
);
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"log prepare commit "
+
sessionId
+
" "
+
transaction
+
" pos:"
+
pos
);
}
if
(
stage
==
RECOVERY_STAGE_UNDO
)
{
int
page
=
pageIn
.
getDataPage
();
setPrepareCommit
(
sessionId
,
page
,
transaction
);
}
}
else
if
(
x
==
ROLLBACK
)
{
int
sessionId
=
in
.
readInt
();
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"log rollback "
+
sessionId
+
" pos:"
+
pos
);
}
// ignore - this entry is just informational
}
else
if
(
x
==
COMMIT
)
{
int
sessionId
=
in
.
readInt
();
if
(
trace
.
isDebugEnabled
())
{
...
...
@@ -220,7 +256,6 @@ public class PageLog {
}
}
if
(
stage
==
RECOVERY_STAGE_REDO
)
{
// TODO probably still required for 2 phase commit
sessionStates
=
New
.
hashMap
();
}
}
catch
(
EOFException
e
)
{
...
...
@@ -230,6 +265,25 @@ public class PageLog {
}
}
/**
* This method is called when a 'prepare commit' log entry is read when
* opening the database.
*
* @param sessionId the session id
* @param the data page with the prepare entry
* @param transaction the transaction name, or null to rollback
*/
private
void
setPrepareCommit
(
int
sessionId
,
int
pageId
,
String
transaction
)
{
SessionState
state
=
getOrAddSessionState
(
sessionId
);
InDoubtTransaction
doubt
;
if
(
transaction
==
null
)
{
doubt
=
null
;
}
else
{
doubt
=
new
InDoubtTransaction
(
store
,
null
,
sessionId
,
pageId
,
transaction
,
0
);
}
state
.
inDoubtTransaction
=
doubt
;
}
/**
* Read a row from an input stream.
*
...
...
@@ -286,14 +340,14 @@ public class PageLog {
}
/**
* Mark a
committed transaction
.
* Mark a
transaction as committed
.
*
* @param session the session
*/
void
commit
(
Session
session
)
throws
SQLException
{
void
commit
(
int
sessionId
)
throws
SQLException
{
try
{
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"log commit s:"
+
session
.
getId
()
);
trace
.
debug
(
"log commit s:"
+
session
Id
);
}
LogSystem
log
=
store
.
getDatabase
().
getLog
();
if
(
log
==
null
)
{
...
...
@@ -301,7 +355,72 @@ public class PageLog {
return
;
}
out
.
write
(
COMMIT
);
out
.
writeInt
(
sessionId
);
flushOut
();
if
(
log
.
getFlushOnEachCommit
())
{
flush
();
}
}
catch
(
IOException
e
)
{
throw
Message
.
convertIOException
(
e
,
null
);
}
}
/**
* Prepare a transaction.
*
* @param session the session
* @param transaction the name of the transaction
*/
void
prepareCommit
(
Session
session
,
String
transaction
)
throws
SQLException
{
try
{
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"log prepare commit s:"
+
session
.
getId
()
+
" "
+
transaction
);
}
LogSystem
log
=
store
.
getDatabase
().
getLog
();
if
(
log
==
null
)
{
// database already closed
return
;
}
// store it on a separate log page
int
pageSize
=
store
.
getPageSize
();
byte
[]
t
=
StringUtils
.
utf8Encode
(
transaction
);
int
len
=
t
.
length
;
if
(
1
+
DataPage
.
LENGTH_INT
*
2
+
len
>=
PageStreamData
.
getCapacity
(
pageSize
))
{
throw
Message
.
getInvalidValueException
(
"transaction name too long"
,
transaction
);
}
pageOut
.
fillDataPage
();
out
.
write
(
PREPARE_COMMIT
);
out
.
writeInt
(
session
.
getId
());
out
.
writeInt
(
len
);
out
.
write
(
t
);
flushOut
();
// store it on a separate log page
pageOut
.
fillDataPage
();
if
(
log
.
getFlushOnEachCommit
())
{
flush
();
}
}
catch
(
IOException
e
)
{
throw
Message
.
convertIOException
(
e
,
null
);
}
}
/**
* Rollback a prepared transaction.
*
* @param session the session
*/
void
rollbackPrepared
(
int
sessionId
)
throws
SQLException
{
try
{
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"log rollback prepared s:"
+
sessionId
);
}
LogSystem
log
=
store
.
getDatabase
().
getLog
();
if
(
log
==
null
)
{
// database already closed
return
;
}
out
.
write
(
ROLLBACK
);
out
.
writeInt
(
sessionId
);
flushOut
();
if
(
log
.
getFlushOnEachCommit
())
{
flush
();
...
...
@@ -452,7 +571,7 @@ public class PageLog {
* @param sessionId the session id
* @return the session state object
*/
private
SessionState
getOrAddSessionState
(
int
sessionId
)
{
SessionState
getOrAddSessionState
(
int
sessionId
)
{
Integer
key
=
sessionId
;
SessionState
state
=
sessionStates
.
get
(
key
);
if
(
state
==
null
)
{
...
...
@@ -463,8 +582,45 @@ public class PageLog {
return
state
;
}
public
long
getSize
()
{
long
getSize
()
{
return
pageOut
.
getSize
();
}
ObjectArray
<
InDoubtTransaction
>
getInDoubtTransactions
()
{
ObjectArray
<
InDoubtTransaction
>
list
=
ObjectArray
.
newInstance
();
for
(
SessionState
state
:
sessionStates
.
values
())
{
InDoubtTransaction
in
=
state
.
inDoubtTransaction
;
if
(
in
!=
null
)
{
list
.
add
(
in
);
}
}
return
list
;
}
/**
* Set the state of an in-doubt transaction.
*
* @param sessionId the session
* @param pageId the page where the commit was prepared
* @param commit whether the transaction should be committed
*/
void
setInDoubtTransactionState
(
int
sessionId
,
int
pageId
,
boolean
commit
)
throws
SQLException
{
PageStreamData
d
=
new
PageStreamData
(
store
,
pageId
,
0
);
d
.
read
();
d
.
initWrite
();
ByteArrayOutputStream
buff
=
new
ByteArrayOutputStream
();
DataOutputStream
o
=
new
DataOutputStream
(
buff
);
try
{
o
.
write
(
commit
?
COMMIT
:
ROLLBACK
);
o
.
writeInt
(
sessionId
);
}
catch
(
IOException
e
)
{
throw
Message
.
convertIOException
(
e
,
""
);
}
byte
[]
bytes
=
buff
.
toByteArray
();
d
.
write
(
buff
.
toByteArray
(),
0
,
bytes
.
length
);
bytes
=
new
byte
[
d
.
getRemaining
()];
d
.
write
(
bytes
,
0
,
bytes
.
length
);
d
.
write
(
null
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageOutputStream.java
浏览文件 @
a67837cb
...
...
@@ -85,7 +85,7 @@ public class PageOutputStream extends OutputStream {
}
private
void
initNextData
()
throws
SQLException
{
int
nextData
=
trunk
==
null
?
-
1
:
trunk
.
getNext
DataPage
();
int
nextData
=
trunk
==
null
?
-
1
:
trunk
.
getNext
PageData
();
if
(
nextData
==
-
1
)
{
int
parent
=
trunkPageId
;
if
(
trunkNext
!=
0
)
{
...
...
@@ -101,7 +101,7 @@ public class PageOutputStream extends OutputStream {
pages
++;
trunk
.
write
(
null
);
reservedPages
.
removeRange
(
0
,
len
+
1
);
nextData
=
trunk
.
getNext
DataPage
();
nextData
=
trunk
.
getNext
PageData
();
}
data
=
new
PageStreamData
(
store
,
nextData
,
trunk
.
getPos
());
pages
++;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStore.java
浏览文件 @
a67837cb
...
...
@@ -20,7 +20,9 @@ import org.h2.index.Index;
import
org.h2.index.IndexType
;
import
org.h2.index.PageBtreeIndex
;
import
org.h2.index.PageScanIndex
;
import
org.h2.log.InDoubtTransaction
;
import
org.h2.log.LogSystem
;
import
org.h2.log.SessionState
;
import
org.h2.message.Message
;
import
org.h2.message.Trace
;
import
org.h2.message.TraceSystem
;
...
...
@@ -69,7 +71,7 @@ import org.h2.value.ValueString;
*/
public
class
PageStore
implements
CacheWriter
{
// TODO Test
SampleApps
// TODO Test
TwoPhaseCommit
// TODO TestIndex.wideIndex: btree nodes should be full
// TODO check memory usage
// TODO PageStore.openMetaIndex (desc and nulls first / last)
...
...
@@ -115,6 +117,7 @@ public class PageStore implements CacheWriter {
// TODO when removing DiskFile:
// remove CacheObject.blockCount
// remove Record.getMemorySize
// simplify InDoubtTransaction
/**
* The smallest possible page size.
...
...
@@ -348,6 +351,7 @@ public class PageStore implements CacheWriter {
}
if
(
writeVersion
!=
0
)
{
close
();
database
.
setReadOnly
(
true
);
accessMode
=
"r"
;
file
=
database
.
openFile
(
fileName
,
accessMode
,
true
);
}
...
...
@@ -520,7 +524,8 @@ public class PageStore implements CacheWriter {
}
private
void
freePage
(
int
pageId
)
throws
SQLException
{
PageFreeList
list
=
getFreeList
(
pageId
/
freeListPagesPerList
);
int
i
=
(
pageId
-
PAGE_ID_FREE_LIST_ROOT
)
/
freeListPagesPerList
;
PageFreeList
list
=
getFreeList
(
i
);
list
.
free
(
pageId
);
}
...
...
@@ -686,32 +691,22 @@ public class PageStore implements CacheWriter {
}
/**
* Run one recovery stage. There are three recovery stages: 0: only the undo
* steps are run (restoring the state before the last checkpoint). 1: the
* pages that are used by the transaction log are allocated. 2: the
* committed operations are re-applied.
* Run recovery.
*/
private
void
recover
()
throws
SQLException
{
trace
.
debug
(
"log recover"
);
try
{
recoveryRunning
=
true
;
log
.
recover
(
PageLog
.
RECOVERY_STAGE_UNDO
);
log
.
recover
(
PageLog
.
RECOVERY_STAGE_ALLOCATE
);
openMetaIndex
();
readMetaData
(
);
log
.
recover
(
PageLog
.
RECOVERY_STAGE_REDO
);
recoveryRunning
=
true
;
log
.
recover
(
PageLog
.
RECOVERY_STAGE_UNDO
)
;
log
.
recover
(
PageLog
.
RECOVERY_STAGE_ALLOCATE
);
openMetaIndex
(
);
readMetaData
();
log
.
recover
(
PageLog
.
RECOVERY_STAGE_REDO
);
if
(
log
.
getInDoubtTransactions
().
size
()
==
0
)
{
switchLog
();
}
catch
(
SQLException
e
)
{
int
test
;
e
.
printStackTrace
();
throw
e
;
}
catch
(
RuntimeException
e
)
{
int
test
;
e
.
printStackTrace
();
throw
e
;
}
finally
{
recoveryRunning
=
false
;
}
else
{
database
.
setReadOnly
(
true
);
}
recoveryRunning
=
false
;
PageScanIndex
index
=
(
PageScanIndex
)
metaObjects
.
get
(
0
);
if
(
index
==
null
)
{
systemTableHeadPos
=
Index
.
EMPTY_HEAD
;
...
...
@@ -721,7 +716,6 @@ public class PageStore implements CacheWriter {
for
(
Index
openIndex
:
metaObjects
.
values
())
{
openIndex
.
close
(
database
.
getSystemSession
());
}
metaObjects
=
null
;
trace
.
debug
(
"log recover done"
);
}
...
...
@@ -748,13 +742,25 @@ public class PageStore implements CacheWriter {
*/
public
void
commit
(
Session
session
)
throws
SQLException
{
synchronized
(
database
)
{
log
.
commit
(
session
);
log
.
commit
(
session
.
getId
()
);
if
(
log
.
getSize
()
>
maxLogSize
)
{
checkpoint
();
}
}
}
/**
* Prepare a transaction.
*
* @param session the session
* @param transaction the name of the transaction
*/
public
void
prepareCommit
(
Session
session
,
String
transaction
)
throws
SQLException
{
synchronized
(
database
)
{
log
.
prepareCommit
(
session
,
transaction
);
}
}
/**
* Get the position of the system table head.
*
...
...
@@ -961,4 +967,31 @@ public class PageStore implements CacheWriter {
this
.
maxLogSize
=
maxSize
;
}
/**
* Commit or rollback a prepared transaction after opening a database with in-doubt
* transactions.
*
* @param sessionId the session id
* @param pageId the page where the transaction was prepared
* @param commit if the transaction should be committed
*/
public
void
setInDoubtTransactionState
(
int
sessionId
,
int
pageId
,
boolean
commit
)
throws
SQLException
{
boolean
old
=
database
.
isReadOnly
();
try
{
database
.
setReadOnly
(
false
);
log
.
setInDoubtTransactionState
(
sessionId
,
pageId
,
commit
);
}
finally
{
database
.
setReadOnly
(
old
);
}
}
/**
* Get the list of in-doubt transaction.
*
* @return the list
*/
public
ObjectArray
<
InDoubtTransaction
>
getInDoubtTransactions
()
{
return
log
.
getInDoubtTransactions
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStreamData.java
浏览文件 @
a67837cb
...
...
@@ -26,7 +26,7 @@ public class PageStreamData extends Record {
private
static
final
int
DATA_START
=
9
;
private
final
PageStore
store
;
private
final
int
trunk
;
private
int
trunk
;
private
DataPage
data
;
private
int
remaining
;
private
int
length
;
...
...
@@ -43,6 +43,7 @@ public class PageStreamData extends Record {
void
read
()
throws
SQLException
{
data
=
store
.
createDataPage
();
store
.
readPage
(
getPos
(),
data
);
trunk
=
data
.
readInt
();
data
.
setPos
(
4
);
int
t
=
data
.
readByte
();
if
(
t
!=
Page
.
TYPE_STREAM_DATA
)
{
...
...
@@ -65,6 +66,7 @@ public class PageStreamData extends Record {
data
.
writeByte
((
byte
)
Page
.
TYPE_STREAM_DATA
);
data
.
writeInt
(
0
);
remaining
=
store
.
getPageSize
()
-
data
.
length
();
length
=
0
;
}
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStreamTrunk.java
浏览文件 @
a67837cb
...
...
@@ -72,7 +72,7 @@ public class PageStreamTrunk extends Record {
pageIds
[
index
++]
=
page
;
}
int
getNext
DataPage
()
{
int
getNext
PageData
()
{
if
(
index
>=
pageIds
.
length
)
{
return
-
1
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/tools/Recover.java
浏览文件 @
a67837cb
...
...
@@ -52,6 +52,7 @@ import org.h2.util.ObjectArray;
import
org.h2.util.RandomUtils
;
import
org.h2.util.SmallLRUCache
;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StringUtils
;
import
org.h2.util.TempFileDeleter
;
import
org.h2.util.Tool
;
import
org.h2.value.Value
;
...
...
@@ -864,6 +865,16 @@ public class Recover extends Tool implements DataHandler {
}
else
if
(
x
==
PageLog
.
COMMIT
)
{
int
sessionId
=
in
.
readInt
();
writer
.
println
(
"-- commit "
+
sessionId
);
}
else
if
(
x
==
PageLog
.
ROLLBACK
)
{
int
sessionId
=
in
.
readInt
();
writer
.
println
(
"-- rollback "
+
sessionId
);
}
else
if
(
x
==
PageLog
.
PREPARE_COMMIT
)
{
int
sessionId
=
in
.
readInt
();
int
len
=
in
.
readInt
();
byte
[]
t
=
new
byte
[
len
];
in
.
readFully
(
t
);
String
transaction
=
StringUtils
.
utf8Decode
(
t
);
writer
.
println
(
"-- prepare commit "
+
sessionId
+
" "
+
transaction
);
}
else
if
(
x
==
PageLog
.
NOOP
)
{
// nothing to do
}
else
if
(
x
==
PageLog
.
CHECKPOINT
)
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论