Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
57386bfa
提交
57386bfa
authored
15 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Page store: various bugfixes.
上级
65cf4260
隐藏空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
430 行增加
和
131 行删除
+430
-131
PageBtree.java
h2/src/main/org/h2/index/PageBtree.java
+18
-2
PageBtreeIndex.java
h2/src/main/org/h2/index/PageBtreeIndex.java
+59
-13
PageBtreeLeaf.java
h2/src/main/org/h2/index/PageBtreeLeaf.java
+3
-1
PageBtreeNode.java
h2/src/main/org/h2/index/PageBtreeNode.java
+36
-8
PageData.java
h2/src/main/org/h2/index/PageData.java
+8
-0
PageDataIndex.java
h2/src/main/org/h2/index/PageDataIndex.java
+28
-17
PageDataLeaf.java
h2/src/main/org/h2/index/PageDataLeaf.java
+9
-1
PageDataNode.java
h2/src/main/org/h2/index/PageDataNode.java
+14
-2
PageDataOverflow.java
h2/src/main/org/h2/index/PageDataOverflow.java
+24
-12
Data.java
h2/src/main/org/h2/store/Data.java
+15
-2
Page.java
h2/src/main/org/h2/store/Page.java
+5
-0
PageFreeList.java
h2/src/main/org/h2/store/PageFreeList.java
+7
-1
PageInputStream.java
h2/src/main/org/h2/store/PageInputStream.java
+23
-40
PageLog.java
h2/src/main/org/h2/store/PageLog.java
+14
-14
PageOutputStream.java
h2/src/main/org/h2/store/PageOutputStream.java
+15
-0
PageStore.java
h2/src/main/org/h2/store/PageStore.java
+55
-12
PageStreamData.java
h2/src/main/org/h2/store/PageStreamData.java
+4
-0
PageStreamTrunk.java
h2/src/main/org/h2/store/PageStreamTrunk.java
+93
-6
没有找到文件。
h2/src/main/org/h2/index/PageBtree.java
浏览文件 @
57386bfa
...
...
@@ -166,7 +166,10 @@ public abstract class PageBtree extends Page {
SearchRow
getRow
(
int
at
)
throws
SQLException
{
SearchRow
row
=
rows
[
at
];
if
(
row
==
null
)
{
row
=
index
.
readRow
(
data
,
offsets
[
at
],
onlyPosition
);
row
=
index
.
readRow
(
data
,
offsets
[
at
],
onlyPosition
,
true
);
rows
[
at
]
=
row
;
}
else
if
(!
index
.
hasData
(
row
))
{
row
=
index
.
readRow
(
row
.
getKey
());
rows
[
at
]
=
row
;
}
return
row
;
...
...
@@ -186,6 +189,7 @@ public abstract class PageBtree extends Page {
* @param id the new page id
*/
void
setPageId
(
int
id
)
throws
SQLException
{
changeCount
=
index
.
getPageStore
().
getChangeCount
();
written
=
false
;
index
.
getPageStore
().
removeRecord
(
getPos
());
setPos
(
id
);
...
...
@@ -214,6 +218,7 @@ public abstract class PageBtree extends Page {
*/
void
setParentPageId
(
int
id
)
throws
SQLException
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
changeCount
=
index
.
getPageStore
().
getChangeCount
();
written
=
false
;
parentPageId
=
id
;
}
...
...
@@ -243,7 +248,11 @@ public abstract class PageBtree extends Page {
*/
protected
void
readAllRows
()
throws
SQLException
{
for
(
int
i
=
0
;
i
<
entryCount
;
i
++)
{
getRow
(
i
);
SearchRow
row
=
rows
[
i
];
if
(
row
==
null
)
{
row
=
index
.
readRow
(
data
,
offsets
[
i
],
onlyPosition
,
false
);
rows
[
i
]
=
row
;
}
}
}
...
...
@@ -257,4 +266,11 @@ public abstract class PageBtree extends Page {
return
index
.
getPageStore
().
getPageSize
();
}
public
boolean
canRemove
()
{
if
(
changeCount
>=
index
.
getPageStore
().
getChangeCount
())
{
return
false
;
}
return
super
.
canRemove
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageBtreeIndex.java
浏览文件 @
57386bfa
...
...
@@ -74,6 +74,14 @@ public class PageBtreeIndex extends PageIndex {
}
// safe memory
SearchRow
newRow
=
getSearchRow
(
row
);
try
{
addRow
(
newRow
);
}
finally
{
store
.
incrementChangeCount
();
}
}
private
void
addRow
(
SearchRow
newRow
)
throws
SQLException
{
while
(
true
)
{
PageBtree
root
=
getPage
(
rootPageId
);
int
splitPoint
=
root
.
addRowTry
(
newRow
);
...
...
@@ -217,10 +225,14 @@ public class PageBtreeIndex extends PageIndex {
if
(
rowCount
==
1
)
{
removeAllRows
();
}
else
{
PageBtree
root
=
getPage
(
rootPageId
);
root
.
remove
(
row
);
invalidateRowCount
();
rowCount
--;
try
{
PageBtree
root
=
getPage
(
rootPageId
);
root
.
remove
(
row
);
invalidateRowCount
();
rowCount
--;
}
finally
{
store
.
incrementChangeCount
();
}
}
}
...
...
@@ -245,12 +257,16 @@ public class PageBtreeIndex extends PageIndex {
}
private
void
removeAllRows
()
throws
SQLException
{
PageBtree
root
=
getPage
(
rootPageId
);
root
.
freeRecursive
();
root
=
PageBtreeLeaf
.
create
(
this
,
rootPageId
,
PageBtree
.
ROOT
);
store
.
removeRecord
(
rootPageId
);
store
.
update
(
root
);
rowCount
=
0
;
try
{
PageBtree
root
=
getPage
(
rootPageId
);
root
.
freeRecursive
();
root
=
PageBtreeLeaf
.
create
(
this
,
rootPageId
,
PageBtree
.
ROOT
);
store
.
removeRecord
(
rootPageId
);
store
.
update
(
root
);
rowCount
=
0
;
}
finally
{
store
.
incrementChangeCount
();
}
}
public
void
checkRename
()
{
...
...
@@ -286,7 +302,11 @@ public class PageBtreeIndex extends PageIndex {
}
// can not close the index because it might get used afterwards,
// for example after running recovery
writeRowCount
();
try
{
writeRowCount
();
}
finally
{
store
.
incrementChangeCount
();
}
}
/**
...
...
@@ -295,13 +315,19 @@ public class PageBtreeIndex extends PageIndex {
* @param data the data
* @param offset the offset
* @param onlyPosition whether only the position of the row is stored
* @param needData whether the row data is required
* @return the row
*/
SearchRow
readRow
(
Data
data
,
int
offset
,
boolean
onlyPosition
)
throws
SQLException
{
SearchRow
readRow
(
Data
data
,
int
offset
,
boolean
onlyPosition
,
boolean
needData
)
throws
SQLException
{
data
.
setPos
(
offset
);
long
key
=
data
.
readVarLong
();
if
(
onlyPosition
)
{
return
tableData
.
getRow
(
null
,
key
);
if
(
needData
)
{
return
tableData
.
getRow
(
null
,
key
);
}
SearchRow
row
=
table
.
getTemplateSimpleRow
(
true
);
row
.
setKey
(
key
);
return
row
;
}
SearchRow
row
=
table
.
getTemplateSimpleRow
(
columns
.
length
==
1
);
row
.
setKey
(
key
);
...
...
@@ -312,6 +338,16 @@ public class PageBtreeIndex extends PageIndex {
return
row
;
}
/**
* Get the complete row from the data index.
*
* @param key the key
* @return the row
*/
SearchRow
readRow
(
long
key
)
throws
SQLException
{
return
tableData
.
getRow
(
null
,
key
);
}
/**
* Write a row to the data page at the given offset.
*
...
...
@@ -377,4 +413,14 @@ public class PageBtreeIndex extends PageIndex {
root
.
setRowCountStored
(
MathUtils
.
convertLongToInt
(
rowCount
));
}
/**
* Check whether the given row contains data.
*
* @param row the row
* @return true if it contains data
*/
boolean
hasData
(
SearchRow
row
)
{
return
row
.
getValue
(
columns
[
0
].
getColumnId
())
!=
null
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageBtreeLeaf.java
浏览文件 @
57386bfa
...
...
@@ -126,6 +126,8 @@ public class PageBtreeLeaf extends PageBtree {
}
}
index
.
getPageStore
().
logUndo
(
this
,
data
);
readAllRows
();
changeCount
=
index
.
getPageStore
().
getChangeCount
();
written
=
false
;
int
offset
=
last
-
rowLength
;
int
[]
newOffsets
=
new
int
[
entryCount
+
1
];
...
...
@@ -134,7 +136,6 @@ public class PageBtreeLeaf extends PageBtree {
if
(
entryCount
==
0
)
{
x
=
0
;
}
else
{
readAllRows
();
x
=
find
(
row
,
false
,
true
,
true
);
System
.
arraycopy
(
offsets
,
0
,
newOffsets
,
0
,
x
);
System
.
arraycopy
(
rows
,
0
,
newRows
,
0
,
x
);
...
...
@@ -161,6 +162,7 @@ public class PageBtreeLeaf extends PageBtree {
index
.
getPageStore
().
logUndo
(
this
,
data
);
entryCount
--;
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
if
(
entryCount
<=
0
)
{
Message
.
throwInternalError
();
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageBtreeNode.java
浏览文件 @
57386bfa
...
...
@@ -29,9 +29,10 @@ import org.h2.util.MemoryUtils;
* <li>count of all children (-1 if not known): int</li>
* <li>entry count: short</li>
* <li>rightmost child page id: int</li>
* <li>entries (child page id: int, offset: short) The row contains the largest
* key of the respective child, meaning row[0] contains the largest key of
* child[0].
* <li>entries (child page id: int, offset: short)</li>
* </ul>
* The row contains the largest key of the respective child,
* meaning row[0] contains the largest key of child[0].
*/
public
class
PageBtreeNode
extends
PageBtree
{
...
...
@@ -79,6 +80,9 @@ public class PageBtreeNode extends PageBtree {
p
.
writeHead
();
// 4 bytes for the rightmost child page id
p
.
start
=
p
.
data
.
length
()
+
4
;
if
(
SysProperties
.
PAGE_STORE_INTERNAL_COUNT
)
{
p
.
rowCount
=
0
;
}
return
p
;
}
...
...
@@ -117,7 +121,7 @@ public class PageBtreeNode extends PageBtree {
* @return the split point of this page, or -1 if no split is required
*/
private
int
addChildTry
(
SearchRow
row
)
throws
SQLException
{
if
(
entryCount
<
2
)
{
if
(
entryCount
<
3
)
{
return
-
1
;
}
int
rowLength
=
index
.
getRowSize
(
data
,
row
,
onlyPosition
);
...
...
@@ -181,8 +185,14 @@ public class PageBtreeNode extends PageBtree {
offsets
=
newOffsets
;
rows
=
newRows
;
childPageIds
=
newChildPageIds
;
if
(
SysProperties
.
PAGE_STORE_INTERNAL_COUNT
)
{
if
(
rowCount
!=
UNKNOWN_ROWCOUNT
)
{
rowCount
+=
offset
;
}
}
entryCount
++;
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
}
int
addRowTry
(
SearchRow
row
)
throws
SQLException
{
...
...
@@ -208,6 +218,7 @@ public class PageBtreeNode extends PageBtree {
}
updateRowCount
(
1
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
return
-
1
;
}
...
...
@@ -236,7 +247,7 @@ public class PageBtreeNode extends PageBtree {
int
firstChild
=
childPageIds
[
splitPoint
];
readAllRows
();
for
(
int
i
=
splitPoint
;
i
<
entryCount
;)
{
p2
.
addChild
(
p2
.
entryCount
,
childPageIds
[
splitPoint
+
1
],
rows
[
splitPoint
]
);
p2
.
addChild
(
p2
.
entryCount
,
childPageIds
[
splitPoint
+
1
],
getRow
(
splitPoint
)
);
removeChild
(
splitPoint
);
}
int
lastChild
=
childPageIds
[
splitPoint
-
1
];
...
...
@@ -271,7 +282,9 @@ public class PageBtreeNode extends PageBtree {
rows
=
new
SearchRow
[
0
];
offsets
=
MemoryUtils
.
EMPTY_INT_ARRAY
;
addChild
(
0
,
page2
.
getPos
(),
pivot
);
rowCount
=
page1
.
getRowCount
()
+
page2
.
getRowCount
();
if
(
SysProperties
.
PAGE_STORE_INTERNAL_COUNT
)
{
rowCount
=
page1
.
getRowCount
()
+
page2
.
getRowCount
();
}
check
();
}
...
...
@@ -313,6 +326,7 @@ public class PageBtreeNode extends PageBtree {
index
.
getPageStore
().
logUndo
(
this
,
data
);
updateRowCount
(-
1
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
if
(
last
==
null
)
{
// the last row didn't change - nothing to do
return
null
;
...
...
@@ -364,11 +378,15 @@ public class PageBtreeNode extends PageBtree {
}
void
setRowCountStored
(
int
rowCount
)
throws
SQLException
{
if
(
rowCount
<
0
&&
SysProperties
.
PAGE_STORE_INTERNAL_COUNT
)
{
return
;
}
this
.
rowCount
=
rowCount
;
if
(
rowCountStored
!=
rowCount
)
{
rowCountStored
=
rowCount
;
index
.
getPageStore
().
logUndo
(
this
,
data
);
if
(
written
)
{
changeCount
=
index
.
getPageStore
().
getChangeCount
();
writeHead
();
}
index
.
getPageStore
().
update
(
this
);
...
...
@@ -422,6 +440,7 @@ public class PageBtreeNode extends PageBtree {
void
freeRecursive
()
throws
SQLException
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
index
.
getPageStore
().
free
(
getPos
());
for
(
int
childPageId
:
childPageIds
)
{
index
.
getPage
(
childPageId
).
freeRecursive
();
}
...
...
@@ -430,7 +449,11 @@ public class PageBtreeNode extends PageBtree {
private
void
removeChild
(
int
i
)
throws
SQLException
{
readAllRows
();
entryCount
--;
if
(
SysProperties
.
PAGE_STORE_INTERNAL_COUNT
)
{
updateRowCount
(-
index
.
getPage
(
childPageIds
[
i
]).
getRowCount
());
}
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
if
(
entryCount
<
0
)
{
Message
.
throwInternalError
();
}
...
...
@@ -536,8 +559,12 @@ public class PageBtreeNode extends PageBtree {
if
(
parentPageId
==
ROOT
)
{
index
.
setRootPageId
(
session
,
newPos
);
}
else
{
PageBtreeNode
p
=
(
PageBtreeNode
)
store
.
getPage
(
parentPageId
);
p
.
moveChild
(
getPos
(),
newPos
);
Page
p
=
store
.
getPage
(
parentPageId
);
if
(!(
p
instanceof
PageBtreeNode
))
{
throw
Message
.
throwInternalError
();
}
PageBtreeNode
n
=
(
PageBtreeNode
)
p
;
n
.
moveChild
(
getPos
(),
newPos
);
}
for
(
int
childPageId
:
childPageIds
)
{
PageBtree
p
=
index
.
getPage
(
childPageId
);
...
...
@@ -558,6 +585,7 @@ public class PageBtreeNode extends PageBtree {
if
(
childPageIds
[
i
]
==
oldPos
)
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
childPageIds
[
i
]
=
newPos
;
index
.
getPageStore
().
update
(
this
);
return
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageData.java
浏览文件 @
57386bfa
...
...
@@ -178,6 +178,7 @@ abstract class PageData extends Page {
index
.
getPageStore
().
logUndo
(
this
,
data
);
parentPageId
=
id
;
if
(
written
)
{
changeCount
=
index
.
getPageStore
().
getChangeCount
();
data
.
setInt
(
START_PARENT
,
parentPageId
);
}
}
...
...
@@ -224,4 +225,11 @@ abstract class PageData extends Page {
return
parentPageId
;
}
public
boolean
canRemove
()
{
if
(
changeCount
>=
index
.
getPageStore
().
getChangeCount
())
{
return
false
;
}
return
super
.
canRemove
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageDataIndex.java
浏览文件 @
57386bfa
...
...
@@ -136,6 +136,8 @@ public class PageDataIndex extends PageIndex implements RowIndex {
row
.
setKey
(
row
.
getKey
()
+
add
);
}
add
++;
}
finally
{
store
.
incrementChangeCount
();
}
}
lastKey
=
Math
.
max
(
lastKey
,
row
.
getKey
()
+
1
);
...
...
@@ -205,9 +207,6 @@ public class PageDataIndex extends PageIndex implements RowIndex {
*/
PageData
getPage
(
int
id
,
int
parent
)
throws
SQLException
{
Page
pd
=
store
.
getPage
(
id
);
if
(
pd
!=
null
&&
!(
pd
instanceof
PageData
))
{
System
.
out
.
println
(
"test"
);
}
PageData
p
=
(
PageData
)
pd
;
if
(
p
==
null
)
{
PageDataLeaf
empty
=
PageDataLeaf
.
create
(
this
,
id
,
parent
);
...
...
@@ -296,11 +295,15 @@ public class PageDataIndex extends PageIndex implements RowIndex {
if
(
rowCount
==
1
)
{
removeAllRows
();
}
else
{
long
key
=
row
.
getKey
();
PageData
root
=
getPage
(
rootPageId
,
0
);
root
.
remove
(
key
);
invalidateRowCount
();
rowCount
--;
try
{
long
key
=
row
.
getKey
();
PageData
root
=
getPage
(
rootPageId
,
0
);
root
.
remove
(
key
);
invalidateRowCount
();
rowCount
--;
}
finally
{
store
.
incrementChangeCount
();
}
}
if
(
database
.
isMultiVersion
())
{
// if storage is null, the delete flag is not yet set
...
...
@@ -342,13 +345,17 @@ public class PageDataIndex extends PageIndex implements RowIndex {
}
private
void
removeAllRows
()
throws
SQLException
{
PageData
root
=
getPage
(
rootPageId
,
0
);
root
.
freeRecursive
();
root
=
PageDataLeaf
.
create
(
this
,
rootPageId
,
PageData
.
ROOT
);
store
.
removeRecord
(
rootPageId
);
store
.
update
(
root
);
rowCount
=
0
;
lastKey
=
0
;
try
{
PageData
root
=
getPage
(
rootPageId
,
0
);
root
.
freeRecursive
();
root
=
PageDataLeaf
.
create
(
this
,
rootPageId
,
PageData
.
ROOT
);
store
.
removeRecord
(
rootPageId
);
store
.
update
(
root
);
rowCount
=
0
;
lastKey
=
0
;
}
finally
{
store
.
incrementChangeCount
();
}
}
public
void
checkRename
()
throws
SQLException
{
...
...
@@ -493,8 +500,12 @@ public class PageDataIndex extends PageIndex implements RowIndex {
}
public
void
writeRowCount
()
throws
SQLException
{
PageData
root
=
getPage
(
rootPageId
,
0
);
root
.
setRowCountStored
(
MathUtils
.
convertLongToInt
(
rowCount
));
try
{
PageData
root
=
getPage
(
rootPageId
,
0
);
root
.
setRowCountStored
(
MathUtils
.
convertLongToInt
(
rowCount
));
}
finally
{
store
.
incrementChangeCount
();
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageDataLeaf.java
浏览文件 @
57386bfa
...
...
@@ -198,6 +198,7 @@ public class PageDataLeaf extends PageData {
}
}
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
last
=
x
==
0
?
pageSize
:
offsets
[
x
-
1
];
offset
=
last
-
rowLength
;
entryCount
++;
...
...
@@ -258,6 +259,7 @@ public class PageDataLeaf extends PageData {
private
void
removeRow
(
int
i
)
throws
SQLException
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
readAllRows
();
Row
r
=
rows
[
i
];
if
(
r
!=
null
)
{
...
...
@@ -409,7 +411,7 @@ public class PageDataLeaf extends PageData {
freeOverflow
();
}
void
freeOverflow
()
throws
SQLException
{
private
void
freeOverflow
()
throws
SQLException
{
if
(
firstOverflowPageId
!=
0
)
{
int
next
=
firstOverflowPageId
;
do
{
...
...
@@ -503,6 +505,11 @@ public class PageDataLeaf extends PageData {
public
void
moveTo
(
Session
session
,
int
newPos
)
throws
SQLException
{
PageStore
store
=
index
.
getPageStore
();
// load the pages into the cache, to ensure old pages
// are written
if
(
parentPageId
!=
ROOT
)
{
store
.
getPage
(
parentPageId
);
}
store
.
logUndo
(
this
,
data
);
PageDataLeaf
p2
=
PageDataLeaf
.
create
(
index
,
newPos
,
parentPageId
);
readAllRows
();
...
...
@@ -543,6 +550,7 @@ public class PageDataLeaf extends PageData {
index
.
getPageStore
().
logUndo
(
this
,
data
);
firstOverflowPageId
=
overflow
;
if
(
written
)
{
changeCount
=
index
.
getPageStore
().
getChangeCount
();
writeHead
();
data
.
writeInt
(
firstOverflowPageId
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageDataNode.java
浏览文件 @
57386bfa
...
...
@@ -115,6 +115,7 @@ public class PageDataNode extends PageData {
private
void
addChild
(
int
x
,
int
childPageId
,
long
key
)
throws
SQLException
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
long
[]
newKeys
=
new
long
[
entryCount
+
1
];
int
[]
newChildPageIds
=
new
int
[
entryCount
+
2
];
if
(
childPageIds
!=
null
)
{
...
...
@@ -305,6 +306,7 @@ public class PageDataNode extends PageData {
rowCountStored
=
rowCount
;
index
.
getPageStore
().
logUndo
(
this
,
data
);
if
(
written
)
{
changeCount
=
index
.
getPageStore
().
getChangeCount
();
writeHead
();
}
index
.
getPageStore
().
update
(
this
);
...
...
@@ -363,6 +365,7 @@ public class PageDataNode extends PageData {
private
void
removeChild
(
int
i
)
throws
SQLException
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
entryCount
--;
int
removedKeyIndex
=
i
<
keys
.
length
?
i
:
i
-
1
;
length
-=
4
+
data
.
getVarLongLen
(
keys
[
removedKeyIndex
]);
...
...
@@ -387,6 +390,14 @@ public class PageDataNode extends PageData {
public
void
moveTo
(
Session
session
,
int
newPos
)
throws
SQLException
{
PageStore
store
=
index
.
getPageStore
();
// load the pages into the cache, to ensure old pages
// are written
for
(
int
child
:
childPageIds
)
{
store
.
getPage
(
child
);
}
if
(
parentPageId
!=
ROOT
)
{
store
.
getPage
(
parentPageId
);
}
store
.
logUndo
(
this
,
data
);
PageDataNode
p2
=
PageDataNode
.
create
(
index
,
newPos
,
parentPageId
);
p2
.
rowCountStored
=
rowCountStored
;
...
...
@@ -402,8 +413,8 @@ public class PageDataNode extends PageData {
PageDataNode
p
=
(
PageDataNode
)
store
.
getPage
(
parentPageId
);
p
.
moveChild
(
getPos
(),
newPos
);
}
for
(
int
i
=
0
;
i
<
childPageIds
.
length
;
i
++
)
{
PageData
p
=
(
PageData
)
store
.
getPage
(
child
PageIds
[
i
]
);
for
(
int
child
:
childPageIds
)
{
PageData
p
=
(
PageData
)
store
.
getPage
(
child
);
p
.
setParentPageId
(
newPos
);
store
.
update
(
p
);
}
...
...
@@ -421,6 +432,7 @@ public class PageDataNode extends PageData {
if
(
childPageIds
[
i
]
==
oldPos
)
{
index
.
getPageStore
().
logUndo
(
this
,
data
);
written
=
false
;
changeCount
=
index
.
getPageStore
().
getChangeCount
();
childPageIds
[
i
]
=
newPos
;
index
.
getPageStore
().
update
(
this
);
return
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/PageDataOverflow.java
浏览文件 @
57386bfa
...
...
@@ -215,26 +215,31 @@ public class PageDataOverflow extends Page {
}
public
void
moveTo
(
Session
session
,
int
newPos
)
throws
SQLException
{
// load the pages into the cache, to ensure old pages
// are written
Page
parent
=
store
.
getPage
(
parentPageId
);
if
(
parent
==
null
)
{
throw
Message
.
throwInternalError
();
}
PageDataOverflow
next
=
null
;
if
(
nextPage
!=
0
)
{
next
=
(
PageDataOverflow
)
store
.
getPage
(
nextPage
);
}
store
.
logUndo
(
this
,
data
);
PageDataOverflow
p2
=
PageDataOverflow
.
create
(
store
,
newPos
,
type
,
parentPageId
,
nextPage
,
data
,
start
,
size
);
store
.
update
(
p2
);
if
(
nextPage
!=
0
)
{
PageDataOverflow
p3
=
(
PageDataOverflow
)
store
.
getPage
(
nextPage
);
p3
.
setParentPageId
(
newPos
);
store
.
update
(
p3
);
if
(
next
!=
null
)
{
next
.
setParentPageId
(
newPos
);
store
.
update
(
next
);
}
Page
p
=
store
.
getPage
(
parentPageId
);
if
(
p
==
null
)
{
throw
Message
.
throwInternalError
();
}
if
(
p
instanceof
PageDataOverflow
)
{
PageDataOverflow
p1
=
(
PageDataOverflow
)
p
;
if
(
parent
instanceof
PageDataOverflow
)
{
PageDataOverflow
p1
=
(
PageDataOverflow
)
parent
;
p1
.
setNext
(
getPos
(),
newPos
);
}
else
{
PageDataLeaf
p1
=
(
PageDataLeaf
)
p
;
PageDataLeaf
p1
=
(
PageDataLeaf
)
p
arent
;
p1
.
setOverflow
(
getPos
(),
newPos
);
}
store
.
update
(
p
);
store
.
update
(
p
arent
);
store
.
free
(
getPos
());
}
...
...
@@ -247,9 +252,16 @@ public class PageDataOverflow extends Page {
data
.
setInt
(
START_NEXT_OVERFLOW
,
nextPage
);
}
/**
* Free this page.
*/
void
free
()
throws
SQLException
{
store
.
logUndo
(
this
,
data
);
store
.
free
(
getPos
());
}
public
boolean
canRemove
()
{
return
super
.
canRemove
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/Data.java
浏览文件 @
57386bfa
...
...
@@ -14,6 +14,7 @@ import java.sql.Date;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.SysProperties
;
import
org.h2.message.Message
;
import
org.h2.util.DateTimeUtils
;
...
...
@@ -46,6 +47,8 @@ import org.h2.value.ValueUuid;
*/
public
class
Data
extends
DataPage
{
private
static
final
int
TEST_OFFSET
=
0
;
private
static
final
int
INT_0_15
=
32
;
private
static
final
int
LONG_0_7
=
48
;
private
static
final
int
DECIMAL_0_1
=
56
;
...
...
@@ -334,11 +337,14 @@ public class Data extends DataPage {
* @param v the value
*/
public
void
writeValue
(
Value
v
)
throws
SQLException
{
int
start
=
pos
;
if
(
TEST_OFFSET
>
0
)
{
pos
+=
TEST_OFFSET
;
}
if
(
v
==
ValueNull
.
INSTANCE
)
{
data
[
pos
++]
=
0
;
return
;
}
int
start
=
pos
;
int
type
=
v
.
getType
();
switch
(
type
)
{
case
Value
.
BOOLEAN
:
...
...
@@ -539,6 +545,9 @@ public class Data extends DataPage {
* @return the value
*/
public
Value
readValue
()
throws
SQLException
{
if
(
TEST_OFFSET
>
0
)
{
pos
+=
TEST_OFFSET
;
}
int
type
=
data
[
pos
++]
&
255
;
switch
(
type
)
{
case
Value
.
NULL
:
...
...
@@ -667,7 +676,7 @@ public class Data extends DataPage {
}
else
if
(
type
>=
STRING_0_31
&&
type
<
STRING_0_31
+
32
)
{
return
ValueString
.
get
(
readString
(
type
-
STRING_0_31
));
}
throw
Message
.
throwInternalError
(
"type=
"
+
type
);
throw
Message
.
getSQLException
(
ErrorCode
.
FILE_CORRUPTED_1
,
"type:
"
+
type
);
}
}
...
...
@@ -678,6 +687,10 @@ public class Data extends DataPage {
* @return the number of bytes required to store this value
*/
public
int
getValueLen
(
Value
v
)
throws
SQLException
{
return
getValueLen2
(
v
)
+
TEST_OFFSET
;
}
private
int
getValueLen2
(
Value
v
)
throws
SQLException
{
if
(
v
==
ValueNull
.
INSTANCE
)
{
return
1
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/Page.java
浏览文件 @
57386bfa
...
...
@@ -69,6 +69,11 @@ public abstract class Page extends Record {
*/
public
static
final
int
TYPE_STREAM_DATA
=
8
;
/**
* When this page was changed the last time.
*/
protected
int
changeCount
;
/**
* Copy the data to a new location, change the parent to point to the new
* location, and free up the current page.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageFreeList.java
浏览文件 @
57386bfa
...
...
@@ -77,7 +77,9 @@ public class PageFreeList extends Page {
while
(
true
)
{
int
free
=
used
.
nextClearBit
(
start
);
if
(
free
>=
pageCount
)
{
full
=
true
;
if
(
start
==
0
)
{
full
=
true
;
}
return
-
1
;
}
if
(
exclude
!=
null
&&
exclude
.
get
(
free
+
getPos
()))
{
...
...
@@ -210,4 +212,8 @@ public class PageFreeList extends Page {
return
"page ["
+
getPos
()
+
"] freeList"
+
(
full
?
"full"
:
""
);
}
public
boolean
canRemove
()
{
return
false
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageInputStream.java
浏览文件 @
57386bfa
...
...
@@ -10,7 +10,6 @@ import java.io.EOFException;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.sql.SQLException
;
import
org.h2.constant.ErrorCode
;
import
org.h2.message.Trace
;
import
org.h2.util.BitField
;
...
...
@@ -21,7 +20,8 @@ public class PageInputStream extends InputStream {
private
PageStore
store
;
private
final
Trace
trace
;
private
int
trunkNext
;
private
int
firstTrunkPage
;
private
PageStreamTrunk
.
Iterator
it
;
private
int
dataPage
;
private
PageStreamTrunk
trunk
;
private
PageStreamData
data
;
...
...
@@ -30,12 +30,13 @@ public class PageInputStream extends InputStream {
private
byte
[]
buffer
=
new
byte
[
1
];
private
int
logKey
;
PageInputStream
(
PageStore
store
,
int
logKey
,
int
t
runkPage
,
int
dataPage
)
{
PageInputStream
(
PageStore
store
,
int
logKey
,
int
firstT
runkPage
,
int
dataPage
)
{
this
.
store
=
store
;
this
.
trace
=
store
.
getTrace
();
// minus one
, because we increment before reading the trunk page
// minus one
because we increment before comparing
this
.
logKey
=
logKey
-
1
;
this
.
trunkNext
=
trunkPage
;
this
.
firstTrunkPage
=
firstTrunkPage
;
it
=
new
PageStreamTrunk
.
Iterator
(
store
,
firstTrunkPage
);
this
.
dataPage
=
dataPage
;
}
...
...
@@ -80,29 +81,20 @@ public class PageInputStream extends InputStream {
}
}
private
void
fillBuffer
()
throws
SQLException
,
EOFException
{
private
void
fillBuffer
()
throws
SQLException
{
if
(
remaining
>
0
||
endOfFile
)
{
return
;
}
if
(
trunkNext
==
0
)
{
endOfFile
=
true
;
return
;
}
int
next
;
while
(
true
)
{
if
(
trunk
==
null
)
{
Page
p
=
store
.
getPage
(
trunkNext
);
if
(
p
instanceof
PageStreamTrunk
)
{
trunk
=
(
PageStreamTrunk
)
p
;
}
trunk
=
it
.
next
();
logKey
++;
if
(
trunk
==
null
)
{
throw
new
EOFException
();
}
else
if
(
trunk
.
getLogKey
()
!=
logKey
)
{
throw
new
EOFException
();
if
(
trunk
==
null
||
trunk
.
getLogKey
()
!=
logKey
)
{
endOfFile
=
true
;
return
;
}
trunk
.
resetIndex
();
trunkNext
=
trunk
.
getNextTrunk
();
}
if
(
trunk
!=
null
)
{
next
=
trunk
.
getNextPageData
();
...
...
@@ -122,10 +114,9 @@ public class PageInputStream extends InputStream {
if
(
p
instanceof
PageStreamData
)
{
data
=
(
PageStreamData
)
p
;
}
if
(
data
==
null
)
{
throw
new
EOFException
();
}
else
if
(
data
.
getLogKey
()
!=
logKey
)
{
throw
new
EOFException
();
if
(
data
==
null
||
data
.
getLogKey
()
!=
logKey
)
{
endOfFile
=
true
;
return
;
}
data
.
initRead
();
remaining
=
data
.
getRemaining
();
...
...
@@ -138,25 +129,18 @@ public class PageInputStream extends InputStream {
*/
BitField
allocateAllPages
()
throws
SQLException
{
BitField
pages
=
new
BitField
();
int
trunkPage
=
trunkNext
;
while
(
trunkPage
!=
0
&&
trunkPage
<
store
.
getPageCount
())
{
pages
.
set
(
trunkPage
);
store
.
allocatePage
(
trunkPage
);
PageStreamTrunk
t
=
null
;
try
{
Page
p
=
store
.
getPage
(
trunkPage
);
if
(
p
instanceof
PageStreamTrunk
)
{
t
=
(
PageStreamTrunk
)
p
;
}
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
!=
ErrorCode
.
FILE_CORRUPTED_1
)
{
// wrong checksum means end of stream
throw
e
;
}
int
key
=
logKey
;
PageStreamTrunk
.
Iterator
it
=
new
PageStreamTrunk
.
Iterator
(
store
,
firstTrunkPage
);
while
(
true
)
{
PageStreamTrunk
t
=
it
.
next
();
key
++;
if
(
it
.
canDelete
())
{
store
.
allocatePage
(
it
.
getCurrentPageId
());
}
if
(
t
==
null
)
{
if
(
t
==
null
||
t
.
getLogKey
()
!=
key
)
{
break
;
}
pages
.
set
(
t
.
getPos
());
t
.
resetIndex
();
while
(
true
)
{
int
n
=
t
.
getNextPageData
();
...
...
@@ -166,7 +150,6 @@ public class PageInputStream extends InputStream {
pages
.
set
(
n
);
store
.
allocatePage
(
n
);
}
trunkPage
=
t
.
getNextTrunk
();
}
return
pages
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageLog.java
浏览文件 @
57386bfa
...
...
@@ -192,22 +192,16 @@ public class PageLog {
* Free up all pages allocated by the log.
*/
void
free
()
throws
SQLException
{
if
(
pageOut
!=
null
)
{
pageOut
.
freeReserved
();
}
PageStreamTrunk
.
Iterator
it
=
new
PageStreamTrunk
.
Iterator
(
store
,
firstTrunkPage
);
while
(
firstTrunkPage
!=
0
&&
firstTrunkPage
<
store
.
getPageCount
())
{
PageStreamTrunk
t
=
null
;
try
{
Page
p
=
store
.
getPage
(
firstTrunkPage
);
if
(
p
instanceof
PageStreamTrunk
)
{
t
=
(
PageStreamTrunk
)
p
;
}
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
!=
ErrorCode
.
FILE_CORRUPTED_1
)
{
// wrong checksum means end of stream
throw
e
;
}
}
PageStreamTrunk
t
=
it
.
next
();
if
(
t
==
null
)
{
store
.
free
(
firstTrunkPage
,
false
);
// EOF
if
(
it
.
canDelete
())
{
store
.
free
(
firstTrunkPage
,
false
);
}
break
;
}
t
.
free
();
...
...
@@ -371,6 +365,12 @@ public class PageLog {
}
}
}
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
FILE_CORRUPTED_1
)
{
trace
.
debug
(
"log recovery stopped: "
+
e
.
toString
());
}
else
{
throw
e
;
}
}
catch
(
EOFException
e
)
{
trace
.
debug
(
"log recovery stopped: "
+
e
.
toString
());
}
catch
(
IOException
e
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageOutputStream.java
浏览文件 @
57386bfa
...
...
@@ -202,4 +202,19 @@ public class PageOutputStream extends OutputStream {
return
trunk
.
getLogKey
();
}
/**
* Free up all reserved pages.
*/
void
freeReserved
()
throws
SQLException
{
if
(
reservedPages
.
size
()
>
0
)
{
int
[]
array
=
new
int
[
reservedPages
.
size
()];
reservedPages
.
toArray
(
array
);
reservedPages
=
new
IntArray
();
reserved
=
0
;
for
(
int
p
:
array
)
{
store
.
free
(
p
);
}
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStore.java
浏览文件 @
57386bfa
...
...
@@ -83,8 +83,12 @@ import org.h2.value.ValueString;
public
class
PageStore
implements
CacheWriter
{
// TODO test running out of disk space (using a special file system)
// TODO test with recovery being the default method
// TODO test reservedPages does not grow unbound
// TODO utf-x: test if it's faster
// TODO corrupt pages should be freed once in a while
// TODO node row counts are incorrect (not splitting row counts)
// TODO after opening the database, delay writing until required
// TODO optimization: try to avoid allocating a byte array per page
// TODO optimization: check if calling Data.getValueLen slows things down
...
...
@@ -130,7 +134,7 @@ public class PageStore implements CacheWriter {
* The default page size.
*/
public
static
final
int
PAGE_SIZE_DEFAULT
=
2
*
1024
;
//
public static final int PAGE_SIZE_DEFAULT = 64;
// public static final int PAGE_SIZE_DEFAULT = 64;
private
static
final
int
PAGE_ID_FREE_LIST_ROOT
=
3
;
private
static
final
int
PAGE_ID_META_ROOT
=
4
;
...
...
@@ -139,8 +143,8 @@ public class PageStore implements CacheWriter {
private
static
final
int
INCREMENT_PAGES
=
128
;
private
static
final
int
READ_VERSION
=
1
;
private
static
final
int
WRITE_VERSION
=
1
;
private
static
final
int
READ_VERSION
=
2
;
private
static
final
int
WRITE_VERSION
=
2
;
private
static
final
int
META_TYPE_SCAN_INDEX
=
0
;
private
static
final
int
META_TYPE_BTREE_INDEX
=
1
;
...
...
@@ -196,6 +200,15 @@ public class PageStore implements CacheWriter {
private
ObjectArray
<
PageFreeList
>
freeLists
=
ObjectArray
.
newInstance
();
/**
* The change count is something like a "micro-transaction-id".
* It is used to ensure that changed pages are not written to the file
* before the the current operation is not finished. This is only a problem
* when using a very small cache size. The value starts at 1 so that
* pages with change count 0 can be evicted from the cache.
*/
private
int
changeCount
=
1
;
/**
* Create a new page store object.
*
...
...
@@ -341,6 +354,9 @@ public class PageStore implements CacheWriter {
if
(
isUsed
(
i
))
{
freed
.
clear
(
i
);
}
else
if
(!
freed
.
get
(
i
))
{
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
"free "
+
i
);
}
freed
.
set
(
i
);
file
.
seek
((
long
)
i
<<
pageSizeShift
);
file
.
write
(
empty
,
0
,
pageSize
);
...
...
@@ -445,7 +461,11 @@ public class PageStore implements CacheWriter {
if
(
p
!=
null
)
{
trace
.
debug
(
"move "
+
p
.
getPos
()
+
" to "
+
free
);
long
logSection
=
log
.
getLogSectionId
(),
logPos
=
log
.
getLogPos
();
p
.
moveTo
(
systemSession
,
free
);
try
{
p
.
moveTo
(
systemSession
,
free
);
}
finally
{
changeCount
++;
}
if
(
log
.
getLogSectionId
()
==
logSection
||
log
.
getLogPos
()
!=
logPos
)
{
commit
(
systemSession
);
}
...
...
@@ -717,9 +737,9 @@ public class PageStore implements CacheWriter {
public
void
logUndo
(
Record
record
,
Data
old
)
throws
SQLException
{
synchronized
(
database
)
{
if
(
trace
.
isDebugEnabled
())
{
if
(!
record
.
isChanged
())
{
trace
.
debug
(
"logUndo "
+
record
.
toString
());
}
//
if (!record.isChanged()) {
//
trace.debug("logUndo " + record.toString());
//
}
}
checkOpen
();
database
.
checkWritingAllowed
();
...
...
@@ -837,23 +857,23 @@ public class PageStore implements CacheWriter {
}
private
int
allocatePage
(
BitField
exclude
,
int
first
)
throws
SQLException
{
int
p
os
;
int
p
age
;
synchronized
(
database
)
{
// TODO could remember the first possible free list page
for
(
int
i
=
0
;;
i
++)
{
PageFreeList
list
=
getFreeList
(
i
);
p
os
=
list
.
allocate
(
exclude
,
first
);
if
(
p
os
>=
0
)
{
p
age
=
list
.
allocate
(
exclude
,
first
);
if
(
p
age
>=
0
)
{
break
;
}
}
if
(
p
os
>=
pageCount
)
{
if
(
p
age
>=
pageCount
)
{
increaseFileSize
(
INCREMENT_PAGES
);
}
if
(
trace
.
isDebugEnabled
())
{
// trace.debug("allocatePage " + pos);
}
return
p
os
;
return
p
age
;
}
}
...
...
@@ -980,6 +1000,13 @@ public class PageStore implements CacheWriter {
Message
.
throwInternalError
(
"write to page "
+
pageId
);
}
byte
[]
bytes
=
data
.
getBytes
();
if
(
SysProperties
.
CHECK
)
{
boolean
shouldBeFreeList
=
(
pageId
-
PAGE_ID_FREE_LIST_ROOT
)
%
freeListPagesPerList
==
0
;
boolean
isFreeList
=
bytes
[
0
]
==
Page
.
TYPE_FREE_LIST
;
if
(
bytes
[
0
]
!=
0
&&
shouldBeFreeList
!=
isFreeList
)
{
throw
Message
.
throwInternalError
();
}
}
checksumSet
(
bytes
,
pageId
);
synchronized
(
database
)
{
file
.
seek
((
long
)
pageId
<<
pageSizeShift
);
...
...
@@ -1558,4 +1585,20 @@ public class PageStore implements CacheWriter {
return
true
;
}
/**
* Increment the change count. To be done after the operation has finished.
*/
public
void
incrementChangeCount
()
{
changeCount
++;
}
/**
* Get the current change count. The first value is 1
*
* @return the change count
*/
public
int
getChangeCount
()
{
return
changeCount
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStreamData.java
浏览文件 @
57386bfa
...
...
@@ -169,4 +169,8 @@ public class PageStreamData extends Page {
return
"["
+
getPos
()
+
"] stream data pos:"
+
data
.
length
()
+
" remaining:"
+
remaining
;
}
public
boolean
canRemove
()
{
return
true
;
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStreamTrunk.java
浏览文件 @
57386bfa
...
...
@@ -7,6 +7,7 @@
package
org
.
h2
.
store
;
import
java.sql.SQLException
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Session
;
/**
...
...
@@ -26,10 +27,18 @@ public class PageStreamTrunk extends Page {
private
static
final
int
DATA_START
=
17
;
/**
* The previous stream trunk.
*/
int
parent
;
/**
* The next stream trunk.
*/
int
nextTrunk
;
private
final
PageStore
store
;
private
int
parent
;
private
int
logKey
;
private
int
nextTrunk
;
private
int
[]
pageIds
;
private
int
pageCount
;
private
Data
data
;
...
...
@@ -115,10 +124,6 @@ public class PageStreamTrunk extends Page {
return
pageIds
[
index
++];
}
int
getNextTrunk
()
{
return
nextTrunk
;
}
public
int
getByteCount
(
DataPage
dummy
)
{
return
store
.
getPageSize
();
}
...
...
@@ -212,4 +217,86 @@ public class PageStreamTrunk extends Page {
return
logKey
;
}
public
int
getNextTrunk
()
{
return
nextTrunk
;
}
/**
* An iterator over page stream trunk pages.
*/
static
class
Iterator
{
private
PageStore
store
;
private
int
first
;
private
int
next
;
private
int
previous
;
private
boolean
canDelete
;
private
int
current
;
Iterator
(
PageStore
store
,
int
first
)
{
this
.
store
=
store
;
this
.
next
=
first
;
}
int
getCurrentPageId
()
{
return
current
;
}
/**
* Get the next trunk page or null if no next trunk page.
*
* @return the next trunk page or null
*/
PageStreamTrunk
next
()
throws
SQLException
{
canDelete
=
false
;
if
(
first
==
0
)
{
first
=
next
;
}
else
if
(
first
==
next
)
{
return
null
;
}
if
(
next
==
0
||
next
>=
store
.
getPageCount
())
{
return
null
;
}
Page
p
;
current
=
next
;
try
{
p
=
store
.
getPage
(
next
);
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
!=
ErrorCode
.
FILE_CORRUPTED_1
)
{
// wrong checksum means end of stream
throw
e
;
}
return
null
;
}
if
(
p
==
null
||
p
instanceof
PageStreamTrunk
||
p
instanceof
PageStreamData
)
{
canDelete
=
true
;
}
if
(!(
p
instanceof
PageStreamTrunk
))
{
return
null
;
}
PageStreamTrunk
t
=
(
PageStreamTrunk
)
p
;
if
(
previous
>
0
&&
t
.
parent
!=
previous
)
{
return
null
;
}
previous
=
next
;
next
=
t
.
nextTrunk
;
return
t
;
}
/**
* Check if the current page can be deleted. It can if it's empty, a
* stream trunk, or a stream data page.
*
* @return true if it can be deleted
*/
boolean
canDelete
()
{
return
canDelete
;
}
}
public
boolean
canRemove
()
{
return
true
;
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论