Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
68446b2c
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
68446b2c
编写于
2月 08, 2010
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Remove some more dead VACUUM-FULL-only code.
上级
0a469c87
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
2 addition
and
464 deletion
+2
-464
src/backend/access/gist/gistvacuum.c
src/backend/access/gist/gistvacuum.c
+2
-464
未找到文件。
src/backend/access/gist/gistvacuum.c
浏览文件 @
68446b2c
/*-------------------------------------------------------------------------
*
* gistvacuum.c
*
interface
routines for the postgres GiST index access method.
*
vacuuming
routines for the postgres GiST index access method.
*
*
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.4
7 2010/02/08 04:33:52
tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.4
8 2010/02/08 05:17:31
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -32,468 +32,6 @@ typedef struct GistBulkDeleteResult
bool
needReindex
;
}
GistBulkDeleteResult
;
typedef
struct
{
GISTSTATE
giststate
;
Relation
index
;
MemoryContext
opCtx
;
GistBulkDeleteResult
*
result
;
BufferAccessStrategy
strategy
;
}
GistVacuum
;
typedef
struct
{
IndexTuple
*
itup
;
int
ituplen
;
bool
emptypage
;
}
ArrayTuple
;
/*
* Make union of keys on page
*/
static
IndexTuple
PageMakeUnionKey
(
GistVacuum
*
gv
,
Buffer
buffer
)
{
Page
page
=
BufferGetPage
(
buffer
);
IndexTuple
*
vec
,
tmp
,
res
;
int
veclen
=
0
;
MemoryContext
oldCtx
=
MemoryContextSwitchTo
(
gv
->
opCtx
);
vec
=
gistextractpage
(
page
,
&
veclen
);
/*
* we call gistunion() in temprorary context because user-defined
* functions called in gistunion() may do not free all memory
*/
tmp
=
gistunion
(
gv
->
index
,
vec
,
veclen
,
&
(
gv
->
giststate
));
MemoryContextSwitchTo
(
oldCtx
);
res
=
(
IndexTuple
)
palloc
(
IndexTupleSize
(
tmp
));
memcpy
(
res
,
tmp
,
IndexTupleSize
(
tmp
));
ItemPointerSetBlockNumber
(
&
(
res
->
t_tid
),
BufferGetBlockNumber
(
buffer
));
GistTupleSetValid
(
res
);
MemoryContextReset
(
gv
->
opCtx
);
return
res
;
}
static
void
gistDeleteSubtree
(
GistVacuum
*
gv
,
BlockNumber
blkno
)
{
Buffer
buffer
;
Page
page
;
buffer
=
ReadBufferExtended
(
gv
->
index
,
MAIN_FORKNUM
,
blkno
,
RBM_NORMAL
,
gv
->
strategy
);
LockBuffer
(
buffer
,
GIST_EXCLUSIVE
);
page
=
(
Page
)
BufferGetPage
(
buffer
);
if
(
!
GistPageIsLeaf
(
page
))
{
int
i
;
for
(
i
=
FirstOffsetNumber
;
i
<=
PageGetMaxOffsetNumber
(
page
);
i
=
OffsetNumberNext
(
i
))
{
ItemId
iid
=
PageGetItemId
(
page
,
i
);
IndexTuple
idxtuple
=
(
IndexTuple
)
PageGetItem
(
page
,
iid
);
gistDeleteSubtree
(
gv
,
ItemPointerGetBlockNumber
(
&
(
idxtuple
->
t_tid
)));
}
}
START_CRIT_SECTION
();
MarkBufferDirty
(
buffer
);
page
=
(
Page
)
BufferGetPage
(
buffer
);
GistPageSetDeleted
(
page
);
gv
->
result
->
std
.
pages_deleted
++
;
if
(
!
gv
->
index
->
rd_istemp
)
{
XLogRecData
rdata
[
2
];
XLogRecPtr
recptr
;
gistxlogPageDelete
xlrec
;
xlrec
.
node
=
gv
->
index
->
rd_node
;
xlrec
.
blkno
=
blkno
;
rdata
[
0
].
buffer
=
buffer
;
rdata
[
0
].
buffer_std
=
true
;
rdata
[
0
].
data
=
NULL
;
rdata
[
0
].
len
=
0
;
rdata
[
0
].
next
=
&
(
rdata
[
1
]);
rdata
[
1
].
buffer
=
InvalidBuffer
;
rdata
[
1
].
data
=
(
char
*
)
&
xlrec
;
rdata
[
1
].
len
=
sizeof
(
gistxlogPageDelete
);
rdata
[
1
].
next
=
NULL
;
recptr
=
XLogInsert
(
RM_GIST_ID
,
XLOG_GIST_PAGE_DELETE
,
rdata
);
PageSetLSN
(
page
,
recptr
);
PageSetTLI
(
page
,
ThisTimeLineID
);
}
else
PageSetLSN
(
page
,
XLogRecPtrForTemp
);
END_CRIT_SECTION
();
UnlockReleaseBuffer
(
buffer
);
}
static
ArrayTuple
vacuumSplitPage
(
GistVacuum
*
gv
,
Page
tempPage
,
Buffer
buffer
,
IndexTuple
*
addon
,
int
curlenaddon
)
{
ArrayTuple
res
=
{
NULL
,
0
,
false
};
IndexTuple
*
vec
;
SplitedPageLayout
*
dist
=
NULL
,
*
ptr
;
int
i
,
veclen
=
0
;
BlockNumber
blkno
=
BufferGetBlockNumber
(
buffer
);
MemoryContext
oldCtx
=
MemoryContextSwitchTo
(
gv
->
opCtx
);
vec
=
gistextractpage
(
tempPage
,
&
veclen
);
vec
=
gistjoinvector
(
vec
,
&
veclen
,
addon
,
curlenaddon
);
dist
=
gistSplit
(
gv
->
index
,
tempPage
,
vec
,
veclen
,
&
(
gv
->
giststate
));
MemoryContextSwitchTo
(
oldCtx
);
if
(
blkno
!=
GIST_ROOT_BLKNO
)
{
/* if non-root split then we should not allocate new buffer */
dist
->
buffer
=
buffer
;
dist
->
page
=
tempPage
;
/* during vacuum we never split leaf page */
GistPageGetOpaque
(
dist
->
page
)
->
flags
=
0
;
}
else
pfree
(
tempPage
);
res
.
itup
=
(
IndexTuple
*
)
palloc
(
sizeof
(
IndexTuple
)
*
veclen
);
res
.
ituplen
=
0
;
/* make new pages and fills them */
for
(
ptr
=
dist
;
ptr
;
ptr
=
ptr
->
next
)
{
char
*
data
;
if
(
ptr
->
buffer
==
InvalidBuffer
)
{
ptr
->
buffer
=
gistNewBuffer
(
gv
->
index
);
GISTInitBuffer
(
ptr
->
buffer
,
0
);
ptr
->
page
=
BufferGetPage
(
ptr
->
buffer
);
}
ptr
->
block
.
blkno
=
BufferGetBlockNumber
(
ptr
->
buffer
);
data
=
(
char
*
)
(
ptr
->
list
);
for
(
i
=
0
;
i
<
ptr
->
block
.
num
;
i
++
)
{
if
(
PageAddItem
(
ptr
->
page
,
(
Item
)
data
,
IndexTupleSize
((
IndexTuple
)
data
),
i
+
FirstOffsetNumber
,
false
,
false
)
==
InvalidOffsetNumber
)
elog
(
ERROR
,
"failed to add item to index page in
\"
%s
\"
"
,
RelationGetRelationName
(
gv
->
index
));
data
+=
IndexTupleSize
((
IndexTuple
)
data
);
}
ItemPointerSetBlockNumber
(
&
(
ptr
->
itup
->
t_tid
),
ptr
->
block
.
blkno
);
res
.
itup
[
res
.
ituplen
]
=
(
IndexTuple
)
palloc
(
IndexTupleSize
(
ptr
->
itup
));
memcpy
(
res
.
itup
[
res
.
ituplen
],
ptr
->
itup
,
IndexTupleSize
(
ptr
->
itup
));
res
.
ituplen
++
;
}
START_CRIT_SECTION
();
for
(
ptr
=
dist
;
ptr
;
ptr
=
ptr
->
next
)
{
MarkBufferDirty
(
ptr
->
buffer
);
GistPageGetOpaque
(
ptr
->
page
)
->
rightlink
=
InvalidBlockNumber
;
}
/* restore splitted non-root page */
if
(
blkno
!=
GIST_ROOT_BLKNO
)
{
PageRestoreTempPage
(
dist
->
page
,
BufferGetPage
(
dist
->
buffer
));
dist
->
page
=
BufferGetPage
(
dist
->
buffer
);
}
if
(
!
gv
->
index
->
rd_istemp
)
{
XLogRecPtr
recptr
;
XLogRecData
*
rdata
;
ItemPointerData
key
;
/* set key for incomplete insert */
char
*
xlinfo
;
ItemPointerSet
(
&
key
,
blkno
,
TUPLE_IS_VALID
);
rdata
=
formSplitRdata
(
gv
->
index
->
rd_node
,
blkno
,
false
,
&
key
,
dist
);
xlinfo
=
rdata
->
data
;
recptr
=
XLogInsert
(
RM_GIST_ID
,
XLOG_GIST_PAGE_SPLIT
,
rdata
);
for
(
ptr
=
dist
;
ptr
;
ptr
=
ptr
->
next
)
{
PageSetLSN
(
BufferGetPage
(
ptr
->
buffer
),
recptr
);
PageSetTLI
(
BufferGetPage
(
ptr
->
buffer
),
ThisTimeLineID
);
}
pfree
(
xlinfo
);
pfree
(
rdata
);
}
else
{
for
(
ptr
=
dist
;
ptr
;
ptr
=
ptr
->
next
)
PageSetLSN
(
BufferGetPage
(
ptr
->
buffer
),
XLogRecPtrForTemp
);
}
for
(
ptr
=
dist
;
ptr
;
ptr
=
ptr
->
next
)
{
/* we must keep the buffer pin on the head page */
if
(
BufferGetBlockNumber
(
ptr
->
buffer
)
!=
blkno
)
UnlockReleaseBuffer
(
ptr
->
buffer
);
}
if
(
blkno
==
GIST_ROOT_BLKNO
)
{
ItemPointerData
key
;
/* set key for incomplete insert */
ItemPointerSet
(
&
key
,
blkno
,
TUPLE_IS_VALID
);
gistnewroot
(
gv
->
index
,
buffer
,
res
.
itup
,
res
.
ituplen
,
&
key
);
}
END_CRIT_SECTION
();
MemoryContextReset
(
gv
->
opCtx
);
return
res
;
}
static
ArrayTuple
gistVacuumUpdate
(
GistVacuum
*
gv
,
BlockNumber
blkno
,
bool
needunion
)
{
ArrayTuple
res
=
{
NULL
,
0
,
false
};
Buffer
buffer
;
Page
page
,
tempPage
=
NULL
;
OffsetNumber
i
,
maxoff
;
ItemId
iid
;
int
lenaddon
=
4
,
curlenaddon
=
0
,
nOffToDelete
=
0
,
nBlkToDelete
=
0
;
IndexTuple
idxtuple
,
*
addon
=
NULL
;
bool
needwrite
=
false
;
OffsetNumber
offToDelete
[
MaxOffsetNumber
];
BlockNumber
blkToDelete
[
MaxOffsetNumber
];
ItemPointerData
*
completed
=
NULL
;
int
ncompleted
=
0
,
lencompleted
=
16
;
vacuum_delay_point
();
buffer
=
ReadBufferExtended
(
gv
->
index
,
MAIN_FORKNUM
,
blkno
,
RBM_NORMAL
,
gv
->
strategy
);
LockBuffer
(
buffer
,
GIST_EXCLUSIVE
);
gistcheckpage
(
gv
->
index
,
buffer
);
page
=
(
Page
)
BufferGetPage
(
buffer
);
maxoff
=
PageGetMaxOffsetNumber
(
page
);
if
(
GistPageIsLeaf
(
page
))
{
if
(
GistTuplesDeleted
(
page
))
needunion
=
needwrite
=
true
;
}
else
{
completed
=
(
ItemPointerData
*
)
palloc
(
sizeof
(
ItemPointerData
)
*
lencompleted
);
addon
=
(
IndexTuple
*
)
palloc
(
sizeof
(
IndexTuple
)
*
lenaddon
);
/* get copy of page to work */
tempPage
=
PageGetTempPageCopy
(
page
);
for
(
i
=
FirstOffsetNumber
;
i
<=
maxoff
;
i
=
OffsetNumberNext
(
i
))
{
ArrayTuple
chldtuple
;
bool
needchildunion
;
iid
=
PageGetItemId
(
tempPage
,
i
);
idxtuple
=
(
IndexTuple
)
PageGetItem
(
tempPage
,
iid
);
needchildunion
=
(
GistTupleIsInvalid
(
idxtuple
))
?
true
:
false
;
if
(
needchildunion
)
elog
(
DEBUG2
,
"gistVacuumUpdate: need union for block %u"
,
ItemPointerGetBlockNumber
(
&
(
idxtuple
->
t_tid
)));
chldtuple
=
gistVacuumUpdate
(
gv
,
ItemPointerGetBlockNumber
(
&
(
idxtuple
->
t_tid
)),
needchildunion
);
if
(
chldtuple
.
ituplen
||
chldtuple
.
emptypage
)
{
/* update tuple or/and inserts new */
if
(
chldtuple
.
emptypage
)
blkToDelete
[
nBlkToDelete
++
]
=
ItemPointerGetBlockNumber
(
&
(
idxtuple
->
t_tid
));
offToDelete
[
nOffToDelete
++
]
=
i
;
PageIndexTupleDelete
(
tempPage
,
i
);
i
--
;
maxoff
--
;
needwrite
=
needunion
=
true
;
if
(
chldtuple
.
ituplen
)
{
Assert
(
chldtuple
.
emptypage
==
false
);
while
(
curlenaddon
+
chldtuple
.
ituplen
>=
lenaddon
)
{
lenaddon
*=
2
;
addon
=
(
IndexTuple
*
)
repalloc
(
addon
,
sizeof
(
IndexTuple
)
*
lenaddon
);
}
memcpy
(
addon
+
curlenaddon
,
chldtuple
.
itup
,
chldtuple
.
ituplen
*
sizeof
(
IndexTuple
));
curlenaddon
+=
chldtuple
.
ituplen
;
if
(
chldtuple
.
ituplen
>
1
)
{
/*
* child was split, so we need mark completion
* insert(split)
*/
int
j
;
while
(
ncompleted
+
chldtuple
.
ituplen
>
lencompleted
)
{
lencompleted
*=
2
;
completed
=
(
ItemPointerData
*
)
repalloc
(
completed
,
sizeof
(
ItemPointerData
)
*
lencompleted
);
}
for
(
j
=
0
;
j
<
chldtuple
.
ituplen
;
j
++
)
{
ItemPointerCopy
(
&
(
chldtuple
.
itup
[
j
]
->
t_tid
),
completed
+
ncompleted
);
ncompleted
++
;
}
}
pfree
(
chldtuple
.
itup
);
}
}
}
Assert
(
maxoff
==
PageGetMaxOffsetNumber
(
tempPage
));
if
(
curlenaddon
)
{
/* insert updated tuples */
if
(
gistnospace
(
tempPage
,
addon
,
curlenaddon
,
InvalidOffsetNumber
,
0
))
{
/* there is no space on page to insert tuples */
res
=
vacuumSplitPage
(
gv
,
tempPage
,
buffer
,
addon
,
curlenaddon
);
tempPage
=
NULL
;
/* vacuumSplitPage() free tempPage */
needwrite
=
needunion
=
false
;
/* gistSplit already forms
* unions and writes pages */
}
else
/* enough free space */
gistfillbuffer
(
tempPage
,
addon
,
curlenaddon
,
InvalidOffsetNumber
);
}
}
/*
* If page is empty, we should remove pointer to it before deleting page
* (except root)
*/
if
(
blkno
!=
GIST_ROOT_BLKNO
&&
(
PageIsEmpty
(
page
)
||
(
tempPage
&&
PageIsEmpty
(
tempPage
))))
{
/*
* New version of page is empty, so leave it unchanged, upper call
* will mark our page as deleted. In case of page split we never will
* be here...
*
* If page was empty it can't become non-empty during processing
*/
res
.
emptypage
=
true
;
UnlockReleaseBuffer
(
buffer
);
}
else
{
/* write page and remove its childs if it need */
START_CRIT_SECTION
();
if
(
tempPage
&&
needwrite
)
{
PageRestoreTempPage
(
tempPage
,
page
);
tempPage
=
NULL
;
}
/* Empty index */
if
(
PageIsEmpty
(
page
)
&&
blkno
==
GIST_ROOT_BLKNO
)
{
needwrite
=
true
;
GistPageSetLeaf
(
page
);
}
if
(
needwrite
)
{
MarkBufferDirty
(
buffer
);
GistClearTuplesDeleted
(
page
);
if
(
!
gv
->
index
->
rd_istemp
)
{
XLogRecData
*
rdata
;
XLogRecPtr
recptr
;
char
*
xlinfo
;
rdata
=
formUpdateRdata
(
gv
->
index
->
rd_node
,
buffer
,
offToDelete
,
nOffToDelete
,
addon
,
curlenaddon
,
NULL
);
xlinfo
=
rdata
->
next
->
data
;
recptr
=
XLogInsert
(
RM_GIST_ID
,
XLOG_GIST_PAGE_UPDATE
,
rdata
);
PageSetLSN
(
page
,
recptr
);
PageSetTLI
(
page
,
ThisTimeLineID
);
pfree
(
xlinfo
);
pfree
(
rdata
);
}
else
PageSetLSN
(
page
,
XLogRecPtrForTemp
);
}
END_CRIT_SECTION
();
if
(
needunion
&&
!
PageIsEmpty
(
page
))
{
res
.
itup
=
(
IndexTuple
*
)
palloc
(
sizeof
(
IndexTuple
));
res
.
ituplen
=
1
;
res
.
itup
[
0
]
=
PageMakeUnionKey
(
gv
,
buffer
);
}
UnlockReleaseBuffer
(
buffer
);
/* delete empty children, now we havn't any links to pointed subtrees */
for
(
i
=
0
;
i
<
nBlkToDelete
;
i
++
)
gistDeleteSubtree
(
gv
,
blkToDelete
[
i
]);
if
(
ncompleted
&&
!
gv
->
index
->
rd_istemp
)
gistxlogInsertCompletion
(
gv
->
index
->
rd_node
,
completed
,
ncompleted
);
}
for
(
i
=
0
;
i
<
curlenaddon
;
i
++
)
pfree
(
addon
[
i
]);
if
(
addon
)
pfree
(
addon
);
if
(
completed
)
pfree
(
completed
);
if
(
tempPage
)
pfree
(
tempPage
);
return
res
;
}
/*
* VACUUM cleanup: update FSM
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录