Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
6d5cba7c
Commit
6d5cba7c
authored
May 29, 2000
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More vacuum cleanup
parent
d950c197
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
247 additions
and
246 deletions
+247
-246
src/backend/commands/vacuum.c
src/backend/commands/vacuum.c
+228
-227
src/include/commands/vacuum.h
src/include/commands/vacuum.h
+19
-19
No files found.
src/backend/commands/vacuum.c
View file @
6d5cba7c
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.15
5 2000/05/29 16:21:0
4 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.15
6 2000/05/29 17:06:1
4 momjian Exp $
*
*-------------------------------------------------------------------------
...
...
@@ -78,20 +78,20 @@ static void vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2);
static
VRelList
getrels
(
NameData
*
VacRelP
);
static
void
vacuum_rel
(
Oid
relid
,
bool
analyze
);
static
void
analyze_rel
(
Oid
relid
,
List
*
anal_cols2
);
static
void
scan_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
PageList
vacuum_pages
,
V
PageList
fraged_pages
);
static
void
repair_frag
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
PageList
vacuum_pages
,
V
PageList
fraged_pages
,
int
nindices
,
Relation
*
Irel
);
static
void
vacuum_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
PageList
vpl
);
static
void
vacuum_page
(
Page
page
,
V
PageDescr
vpd
);
static
void
vacuum_index
(
V
PageList
vpl
,
Relation
indrel
,
int
num_tuples
,
int
keep_tuples
);
static
void
scan_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
acPageList
vacuum_pages
,
Vac
PageList
fraged_pages
);
static
void
repair_frag
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
acPageList
vacuum_pages
,
Vac
PageList
fraged_pages
,
int
nindices
,
Relation
*
Irel
);
static
void
vacuum_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
acPageList
vacpagelist
);
static
void
vacuum_page
(
Page
page
,
V
acPage
vacpage
);
static
void
vacuum_index
(
V
acPageList
vacpagelist
,
Relation
indrel
,
int
num_tuples
,
int
keep_tuples
);
static
void
scan_index
(
Relation
indrel
,
int
num_tuples
);
static
void
attr_stats
(
Relation
onerel
,
int
attr_cnt
,
VacAttrStats
*
vacattrstats
,
HeapTuple
tuple
);
static
void
bucketcpy
(
Form_pg_attribute
attr
,
Datum
value
,
Datum
*
bucket
,
int
*
bucket_len
);
static
void
update_relstats
(
Oid
relid
,
int
num_pages
,
int
num_tuples
,
bool
hasindex
,
VRelStats
*
vacrelstats
);
static
void
update_attstats
(
Oid
relid
,
int
natts
,
VacAttrStats
*
vacattrstats
);
static
void
del_stats
(
Oid
relid
,
int
attcnt
,
int
*
attnums
);
static
V
PageDescr
tid_reaped
(
ItemPointer
itemptr
,
VPageList
vpl
);
static
void
reap_page
(
V
PageList
vpl
,
VPageDescr
vpc
);
static
void
vpage_insert
(
V
PageList
vpl
,
VPageDescr
vpnew
);
static
V
acPage
tid_reaped
(
ItemPointer
itemptr
,
VacPageList
vacpagelist
);
static
void
reap_page
(
V
acPageList
vacpagelist
,
VacPage
vacpage
);
static
void
vpage_insert
(
V
acPageList
vacpagelist
,
VacPage
vpnew
);
static
void
get_indices
(
Oid
relid
,
int
*
nindices
,
Relation
**
Irel
);
static
void
close_indices
(
int
nindices
,
Relation
*
Irel
);
static
void
get_index_desc
(
Relation
onerel
,
int
nindices
,
Relation
*
Irel
,
IndDesc
**
Idesc
);
...
...
@@ -100,7 +100,7 @@ static void *vac_find_eq(void *bot, int nelem, int size, void *elm,
static
int
vac_cmp_blk
(
const
void
*
left
,
const
void
*
right
);
static
int
vac_cmp_offno
(
const
void
*
left
,
const
void
*
right
);
static
int
vac_cmp_vtlinks
(
const
void
*
left
,
const
void
*
right
);
static
bool
enough_space
(
V
PageDescr
vpd
,
Size
len
);
static
bool
enough_space
(
V
acPage
vacpage
,
Size
len
);
static
char
*
show_rusage
(
struct
rusage
*
ru0
);
/* CommonSpecialPortal function at the bottom */
...
...
@@ -363,11 +363,11 @@ vacuum_rel(Oid relid, bool analyze)
{
HeapTuple
tuple
;
Relation
onerel
;
VPageListData
vacuum_pages
;
/* List of pages to vacuum and/or clean
V
ac
PageListData
vacuum_pages
;
/* List of pages to vacuum and/or clean
* indices */
VPageListData
fraged_pages
;
/* List of pages with space enough for
V
ac
PageListData
fraged_pages
;
/* List of pages with space enough for
* re-using */
V
PageDescr
*
vpp
;
V
acPage
*
vacpage
;
Relation
*
Irel
;
int32
nindices
,
i
;
...
...
@@ -428,7 +428,7 @@ vacuum_rel(Oid relid, bool analyze)
/* scan it */
reindex
=
false
;
vacuum_pages
.
vpl_num_pages
=
fraged_pages
.
vpl_
num_pages
=
0
;
vacuum_pages
.
num_pages
=
fraged_pages
.
num_pages
=
0
;
scan_heap
(
vacrelstats
,
onerel
,
&
vacuum_pages
,
&
fraged_pages
);
if
(
IsIgnoringSystemIndexes
()
&&
IsSystemRelationName
(
RelationGetRelationName
(
onerel
)))
reindex
=
true
;
...
...
@@ -456,7 +456,7 @@ vacuum_rel(Oid relid, bool analyze)
/* Clean/scan index relation(s) */
if
(
Irel
!=
(
Relation
*
)
NULL
)
{
if
(
vacuum_pages
.
vpl_
num_pages
>
0
)
if
(
vacuum_pages
.
num_pages
>
0
)
{
for
(
i
=
0
;
i
<
nindices
;
i
++
)
vacuum_index
(
&
vacuum_pages
,
Irel
[
i
],
vacrelstats
->
num_tuples
,
0
);
...
...
@@ -469,13 +469,13 @@ vacuum_rel(Oid relid, bool analyze)
}
}
if
(
fraged_pages
.
vpl_
num_pages
>
0
)
/* Try to shrink heap */
if
(
fraged_pages
.
num_pages
>
0
)
/* Try to shrink heap */
repair_frag
(
vacrelstats
,
onerel
,
&
vacuum_pages
,
&
fraged_pages
,
nindices
,
Irel
);
else
{
if
(
Irel
!=
(
Relation
*
)
NULL
)
close_indices
(
nindices
,
Irel
);
if
(
vacuum_pages
.
vpl_
num_pages
>
0
)
/* Clean pages from
if
(
vacuum_pages
.
num_pages
>
0
)
/* Clean pages from
* vacuum_pages list */
vacuum_heap
(
vacrelstats
,
onerel
,
&
vacuum_pages
);
}
...
...
@@ -483,14 +483,14 @@ vacuum_rel(Oid relid, bool analyze)
activate_indexes_of_a_table
(
relid
,
true
);
/* ok - free vacuum_pages list of reaped pages */
if
(
vacuum_pages
.
vpl_
num_pages
>
0
)
if
(
vacuum_pages
.
num_pages
>
0
)
{
v
pp
=
vacuum_pages
.
vpl_
pagedesc
;
for
(
i
=
0
;
i
<
vacuum_pages
.
vpl_num_pages
;
i
++
,
vpp
++
)
pfree
(
*
v
pp
);
pfree
(
vacuum_pages
.
vpl_
pagedesc
);
if
(
fraged_pages
.
vpl_
num_pages
>
0
)
pfree
(
fraged_pages
.
vpl_
pagedesc
);
v
acpage
=
vacuum_pages
.
pagedesc
;
for
(
i
=
0
;
i
<
vacuum_pages
.
num_pages
;
i
++
,
vacpage
++
)
pfree
(
*
v
acpage
);
pfree
(
vacuum_pages
.
pagedesc
);
if
(
fraged_pages
.
num_pages
>
0
)
pfree
(
fraged_pages
.
pagedesc
);
}
/* all done with this class, but hold lock until commit */
...
...
@@ -691,7 +691,7 @@ analyze_rel(Oid relid, List *anal_cols2)
*/
static
void
scan_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
PageList
vacuum_pages
,
V
PageList
fraged_pages
)
V
acPageList
vacuum_pages
,
Vac
PageList
fraged_pages
)
{
BlockNumber
nblocks
,
blkno
;
...
...
@@ -707,7 +707,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
dobufrel
,
notup
;
char
*
relname
;
V
PageDescr
vpc
,
V
acPage
vacpage
,
vp
;
uint32
tups_vacuumed
,
num_tuples
,
...
...
@@ -740,37 +740,37 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
nblocks
=
RelationGetNumberOfBlocks
(
onerel
);
v
pc
=
(
VPageDescr
)
palloc
(
sizeof
(
VPageDescr
Data
)
+
MaxOffsetNumber
*
sizeof
(
OffsetNumber
));
v
pc
->
vpd_
offsets_used
=
0
;
v
acpage
=
(
VacPage
)
palloc
(
sizeof
(
VacPage
Data
)
+
MaxOffsetNumber
*
sizeof
(
OffsetNumber
));
v
acpage
->
offsets_used
=
0
;
for
(
blkno
=
0
;
blkno
<
nblocks
;
blkno
++
)
{
buf
=
ReadBuffer
(
onerel
,
blkno
);
page
=
BufferGetPage
(
buf
);
v
pc
->
vpd_
blkno
=
blkno
;
v
pc
->
vpd_
offsets_free
=
0
;
v
acpage
->
blkno
=
blkno
;
v
acpage
->
offsets_free
=
0
;
if
(
PageIsNew
(
page
))
{
elog
(
NOTICE
,
"Rel %s: Uninitialized page %u - fixing"
,
relname
,
blkno
);
PageInit
(
page
,
BufferGetPageSize
(
buf
),
0
);
v
pc
->
vpd_
free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
free_size
+=
(
v
pc
->
vpd_
free
-
sizeof
(
ItemIdData
));
v
acpage
->
free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
free_size
+=
(
v
acpage
->
free
-
sizeof
(
ItemIdData
));
new_pages
++
;
empty_end_pages
++
;
reap_page
(
vacuum_pages
,
v
pc
);
reap_page
(
vacuum_pages
,
v
acpage
);
WriteBuffer
(
buf
);
continue
;
}
if
(
PageIsEmpty
(
page
))
{
v
pc
->
vpd_
free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
free_size
+=
(
v
pc
->
vpd_
free
-
sizeof
(
ItemIdData
));
v
acpage
->
free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
free_size
+=
(
v
acpage
->
free
-
sizeof
(
ItemIdData
));
empty_pages
++
;
empty_end_pages
++
;
reap_page
(
vacuum_pages
,
v
pc
);
reap_page
(
vacuum_pages
,
v
acpage
);
ReleaseBuffer
(
buf
);
continue
;
}
...
...
@@ -790,7 +790,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
*/
if
(
!
ItemIdIsUsed
(
itemid
))
{
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
offnum
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
offnum
;
nunused
++
;
continue
;
}
...
...
@@ -974,7 +974,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
/* mark it unused */
lpp
->
lp_flags
&=
~
LP_USED
;
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
offnum
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
offnum
;
tups_vacuumed
++
;
}
...
...
@@ -1001,17 +1001,17 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
if
(
tempPage
!=
(
Page
)
NULL
)
{
/* Some tuples are gone */
PageRepairFragmentation
(
tempPage
);
v
pc
->
vpd_
free
=
((
PageHeader
)
tempPage
)
->
pd_upper
-
((
PageHeader
)
tempPage
)
->
pd_lower
;
free_size
+=
v
pc
->
vpd_
free
;
reap_page
(
vacuum_pages
,
v
pc
);
v
acpage
->
free
=
((
PageHeader
)
tempPage
)
->
pd_upper
-
((
PageHeader
)
tempPage
)
->
pd_lower
;
free_size
+=
v
acpage
->
free
;
reap_page
(
vacuum_pages
,
v
acpage
);
pfree
(
tempPage
);
tempPage
=
(
Page
)
NULL
;
}
else
if
(
v
pc
->
vpd_
offsets_free
>
0
)
else
if
(
v
acpage
->
offsets_free
>
0
)
{
/* there are only ~LP_USED line pointers */
v
pc
->
vpd_
free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
free_size
+=
v
pc
->
vpd_
free
;
reap_page
(
vacuum_pages
,
v
pc
);
v
acpage
->
free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
free_size
+=
v
acpage
->
free
;
reap_page
(
vacuum_pages
,
v
acpage
);
}
if
(
dobufrel
)
ReleaseBuffer
(
buf
);
...
...
@@ -1021,7 +1021,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
empty_end_pages
=
0
;
}
pfree
(
v
pc
);
pfree
(
v
acpage
);
/* save stats in the rel list for use later */
vacrelstats
->
num_tuples
=
num_tuples
;
...
...
@@ -1032,28 +1032,28 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
vacrelstats
->
min_tlen
=
min_tlen
;
vacrelstats
->
max_tlen
=
max_tlen
;
vacuum_pages
->
vpl_
empty_end_pages
=
empty_end_pages
;
fraged_pages
->
vpl_
empty_end_pages
=
empty_end_pages
;
vacuum_pages
->
empty_end_pages
=
empty_end_pages
;
fraged_pages
->
empty_end_pages
=
empty_end_pages
;
/*
* Try to make fraged_pages keeping in mind that we can't use free
* space of "empty" end-pages and last page if it reaped.
*/
if
(
do_shrinking
&&
vacuum_pages
->
vpl_
num_pages
-
empty_end_pages
>
0
)
if
(
do_shrinking
&&
vacuum_pages
->
num_pages
-
empty_end_pages
>
0
)
{
int
nusf
;
/* blocks usefull for re-using */
nusf
=
vacuum_pages
->
vpl_
num_pages
-
empty_end_pages
;
if
((
vacuum_pages
->
vpl_pagedesc
[
nusf
-
1
])
->
vpd_
blkno
==
nblocks
-
empty_end_pages
-
1
)
nusf
=
vacuum_pages
->
num_pages
-
empty_end_pages
;
if
((
vacuum_pages
->
pagedesc
[
nusf
-
1
])
->
blkno
==
nblocks
-
empty_end_pages
-
1
)
nusf
--
;
for
(
i
=
0
;
i
<
nusf
;
i
++
)
{
vp
=
vacuum_pages
->
vpl_
pagedesc
[
i
];
vp
=
vacuum_pages
->
pagedesc
[
i
];
if
(
enough_space
(
vp
,
min_tlen
))
{
vpage_insert
(
fraged_pages
,
vp
);
usable_free_size
+=
vp
->
vpd_
free
;
usable_free_size
+=
vp
->
free
;
}
}
}
...
...
@@ -1075,11 +1075,11 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
elog
(
MESSAGE_LEVEL
,
"Pages %u: Changed %u, reaped %u, Empty %u, New %u; \
Tup %u: Vac %u, Keep/VTL %u/%u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; \
Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. %s"
,
nblocks
,
changed_pages
,
vacuum_pages
->
vpl_
num_pages
,
empty_pages
,
nblocks
,
changed_pages
,
vacuum_pages
->
num_pages
,
empty_pages
,
new_pages
,
num_tuples
,
tups_vacuumed
,
nkeep
,
vacrelstats
->
num_vtlinks
,
ncrash
,
nunused
,
min_tlen
,
max_tlen
,
free_size
,
usable_free_size
,
empty_end_pages
,
fraged_pages
->
vpl_
num_pages
,
empty_end_pages
,
fraged_pages
->
num_pages
,
show_rusage
(
&
ru0
));
}
...
...
@@ -1090,14 +1090,14 @@ Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. %s",
*
* This routine marks dead tuples as unused and tries re-use dead space
* by moving tuples (and inserting indices if needed). It constructs
* Nv
pl
list of free-ed pages (moved tuples) and clean indices
* Nv
acpagelist
list of free-ed pages (moved tuples) and clean indices
* for them after committing (in hack-manner - without losing locks
* and freeing memory!) current transaction. It truncates relation
* if some end-blocks are gone away.
*/
static
void
repair_frag
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
PageList
vacuum_pages
,
V
PageList
fraged_pages
,
V
acPageList
vacuum_pages
,
Vac
PageList
fraged_pages
,
int
nindices
,
Relation
*
Irel
)
{
TransactionId
myXID
;
...
...
@@ -1120,11 +1120,11 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
Datum
*
idatum
=
NULL
;
char
*
inulls
=
NULL
;
InsertIndexResult
iresult
;
V
PageListData
Nvpl
;
V
PageDescr
cur_page
=
NULL
,
V
acPageListData
Nvacpagelist
;
V
acPage
cur_page
=
NULL
,
last_vacuum_page
,
v
pc
,
*
vpp
;
v
acpage
,
*
curpage
;
int
cur_item
=
0
;
IndDesc
*
Idesc
,
*
idcur
;
...
...
@@ -1156,17 +1156,17 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
inulls
=
(
char
*
)
palloc
(
INDEX_MAX_KEYS
*
sizeof
(
*
inulls
));
}
Nv
pl
.
vpl_
num_pages
=
0
;
num_fraged_pages
=
fraged_pages
->
vpl_
num_pages
;
Assert
(
vacuum_pages
->
vpl_num_pages
>
vacuum_pages
->
vpl_
empty_end_pages
);
vacuumed_pages
=
vacuum_pages
->
vpl_num_pages
-
vacuum_pages
->
vpl_
empty_end_pages
;
last_vacuum_page
=
vacuum_pages
->
vpl_
pagedesc
[
vacuumed_pages
-
1
];
last_vacuum_block
=
last_vacuum_page
->
vpd_
blkno
;
Nv
acpagelist
.
num_pages
=
0
;
num_fraged_pages
=
fraged_pages
->
num_pages
;
Assert
(
vacuum_pages
->
num_pages
>
vacuum_pages
->
empty_end_pages
);
vacuumed_pages
=
vacuum_pages
->
num_pages
-
vacuum_pages
->
empty_end_pages
;
last_vacuum_page
=
vacuum_pages
->
pagedesc
[
vacuumed_pages
-
1
];
last_vacuum_block
=
last_vacuum_page
->
blkno
;
cur_buffer
=
InvalidBuffer
;
num_moved
=
0
;
v
pc
=
(
VPageDescr
)
palloc
(
sizeof
(
VPageDescr
Data
)
+
MaxOffsetNumber
*
sizeof
(
OffsetNumber
));
v
pc
->
vpd_offsets_used
=
vpc
->
vpd_
offsets_free
=
0
;
v
acpage
=
(
VacPage
)
palloc
(
sizeof
(
VacPage
Data
)
+
MaxOffsetNumber
*
sizeof
(
OffsetNumber
));
v
acpage
->
offsets_used
=
vacpage
->
offsets_free
=
0
;
/*
* Scan pages backwards from the last nonempty page, trying to move
...
...
@@ -1180,21 +1180,21 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* in order, and on fraged_pages being a subset of vacuum_pages.
*/
nblocks
=
vacrelstats
->
num_pages
;
for
(
blkno
=
nblocks
-
vacuum_pages
->
vpl_
empty_end_pages
-
1
;
for
(
blkno
=
nblocks
-
vacuum_pages
->
empty_end_pages
-
1
;
blkno
>
last_move_dest_block
;
blkno
--
)
{
buf
=
ReadBuffer
(
onerel
,
blkno
);
page
=
BufferGetPage
(
buf
);
v
pc
->
vpd_
offsets_free
=
0
;
v
acpage
->
offsets_free
=
0
;
isempty
=
PageIsEmpty
(
page
);
dowrite
=
false
;
if
(
blkno
==
last_vacuum_block
)
/* it's reaped page */
{
if
(
last_vacuum_page
->
vpd_
offsets_free
>
0
)
/* there are dead tuples */
if
(
last_vacuum_page
->
offsets_free
>
0
)
/* there are dead tuples */
{
/* on this page - clean */
Assert
(
!
isempty
);
vacuum_page
(
page
,
last_vacuum_page
);
...
...
@@ -1206,8 +1206,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if
(
vacuumed_pages
>
0
)
{
/* get prev reaped page from vacuum_pages */
last_vacuum_page
=
vacuum_pages
->
vpl_
pagedesc
[
vacuumed_pages
-
1
];
last_vacuum_block
=
last_vacuum_page
->
vpd_
blkno
;
last_vacuum_page
=
vacuum_pages
->
pagedesc
[
vacuumed_pages
-
1
];
last_vacuum_block
=
last_vacuum_page
->
blkno
;
}
else
{
...
...
@@ -1215,7 +1215,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
last_vacuum_block
=
-
1
;
}
if
(
num_fraged_pages
>
0
&&
fraged_pages
->
vpl_pagedesc
[
num_fraged_pages
-
1
]
->
vpd_
blkno
==
fraged_pages
->
pagedesc
[
num_fraged_pages
-
1
]
->
blkno
==
(
BlockNumber
)
blkno
)
{
/* page is in fraged_pages too; remove it */
...
...
@@ -1232,7 +1232,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
chain_tuple_moved
=
false
;
/* no one chain-tuple was moved
* off this page, yet */
v
pc
->
vpd_
blkno
=
blkno
;
v
acpage
->
blkno
=
blkno
;
maxoff
=
PageGetMaxOffsetNumber
(
page
);
for
(
offnum
=
FirstOffsetNumber
;
offnum
<=
maxoff
;
...
...
@@ -1257,7 +1257,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/*
* If this (chain) tuple is moved by me already then I
* have to check is it in v
pc
or not - i.e. is it moved
* have to check is it in v
acpage
or not - i.e. is it moved
* while cleaning this page or some previous one.
*/
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_OFF
)
...
...
@@ -1267,21 +1267,21 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if
(
chain_tuple_moved
)
/* some chains was moved
* while */
{
/* cleaning this page */
Assert
(
v
pc
->
vpd_
offsets_free
>
0
);
for
(
i
=
0
;
i
<
v
pc
->
vpd_
offsets_free
;
i
++
)
Assert
(
v
acpage
->
offsets_free
>
0
);
for
(
i
=
0
;
i
<
v
acpage
->
offsets_free
;
i
++
)
{
if
(
v
pc
->
vpd_
offsets
[
i
]
==
offnum
)
if
(
v
acpage
->
offsets
[
i
]
==
offnum
)
break
;
}
if
(
i
>=
v
pc
->
vpd_
offsets_free
)
/* not found */
if
(
i
>=
v
acpage
->
offsets_free
)
/* not found */
{
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
offnum
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
offnum
;
keep_tuples
--
;
}
}
else
{
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
offnum
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
offnum
;
keep_tuples
--
;
}
continue
;
...
...
@@ -1309,7 +1309,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
palloc
(
100
*
sizeof
(
VTupleMoveData
));
int
num_vtmove
=
0
;
int
free_vtmove
=
100
;
V
PageDescr
to_vpd
=
NULL
;
V
acPage
to_vacpage
=
NULL
;
int
to_item
=
0
;
bool
freeCbuf
=
false
;
int
ti
;
...
...
@@ -1366,26 +1366,26 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* first, can chain be moved ? */
for
(;;)
{
if
(
to_v
pd
==
NULL
||
!
enough_space
(
to_v
pd
,
tlen
))
if
(
to_v
acpage
==
NULL
||
!
enough_space
(
to_v
acpage
,
tlen
))
{
/*
* if to_v
pd
no longer has enough free space to be
* if to_v
acpage
no longer has enough free space to be
* useful, remove it from fraged_pages list
*/
if
(
to_v
pd
!=
NULL
&&
!
enough_space
(
to_v
pd
,
vacrelstats
->
min_tlen
))
if
(
to_v
acpage
!=
NULL
&&
!
enough_space
(
to_v
acpage
,
vacrelstats
->
min_tlen
))
{
Assert
(
num_fraged_pages
>
to_item
);
memmove
(
fraged_pages
->
vpl_
pagedesc
+
to_item
,
fraged_pages
->
vpl_
pagedesc
+
to_item
+
1
,
sizeof
(
V
PageDescr
)
*
(
num_fraged_pages
-
to_item
-
1
));
memmove
(
fraged_pages
->
pagedesc
+
to_item
,
fraged_pages
->
pagedesc
+
to_item
+
1
,
sizeof
(
V
acPage
)
*
(
num_fraged_pages
-
to_item
-
1
));
num_fraged_pages
--
;
}
for
(
i
=
0
;
i
<
num_fraged_pages
;
i
++
)
{
if
(
enough_space
(
fraged_pages
->
vpl_
pagedesc
[
i
],
tlen
))
if
(
enough_space
(
fraged_pages
->
pagedesc
[
i
],
tlen
))
break
;
}
...
...
@@ -1394,19 +1394,19 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
{
for
(
i
=
0
;
i
<
num_vtmove
;
i
++
)
{
Assert
(
vtmove
[
i
].
v
pd
->
vpd_
offsets_used
>
0
);
(
vtmove
[
i
].
v
pd
->
vpd_
offsets_used
)
--
;
Assert
(
vtmove
[
i
].
v
acpage
->
offsets_used
>
0
);
(
vtmove
[
i
].
v
acpage
->
offsets_used
)
--
;
}
num_vtmove
=
0
;
break
;
}
to_item
=
i
;
to_v
pd
=
fraged_pages
->
vpl_
pagedesc
[
to_item
];
to_v
acpage
=
fraged_pages
->
pagedesc
[
to_item
];
}
to_v
pd
->
vpd_
free
-=
MAXALIGN
(
tlen
);
if
(
to_v
pd
->
vpd_offsets_used
>=
to_vpd
->
vpd_
offsets_free
)
to_v
pd
->
vpd_
free
-=
MAXALIGN
(
sizeof
(
ItemIdData
));
(
to_v
pd
->
vpd_
offsets_used
)
++
;
to_v
acpage
->
free
-=
MAXALIGN
(
tlen
);
if
(
to_v
acpage
->
offsets_used
>=
to_vacpage
->
offsets_free
)
to_v
acpage
->
free
-=
MAXALIGN
(
sizeof
(
ItemIdData
));
(
to_v
acpage
->
offsets_used
)
++
;
if
(
free_vtmove
==
0
)
{
free_vtmove
=
1000
;
...
...
@@ -1415,8 +1415,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
sizeof
(
VTupleMoveData
));
}
vtmove
[
num_vtmove
].
tid
=
tp
.
t_self
;
vtmove
[
num_vtmove
].
v
pd
=
to_vpd
;
if
(
to_v
pd
->
vpd_
offsets_used
==
1
)
vtmove
[
num_vtmove
].
v
acpage
=
to_vacpage
;
if
(
to_v
acpage
->
offsets_used
==
1
)
vtmove
[
num_vtmove
].
cleanVpd
=
true
;
else
vtmove
[
num_vtmove
].
cleanVpd
=
false
;
...
...
@@ -1481,8 +1481,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
ReleaseBuffer
(
Pbuf
);
for
(
i
=
0
;
i
<
num_vtmove
;
i
++
)
{
Assert
(
vtmove
[
i
].
v
pd
->
vpd_
offsets_used
>
0
);
(
vtmove
[
i
].
v
pd
->
vpd_
offsets_used
)
--
;
Assert
(
vtmove
[
i
].
v
acpage
->
offsets_used
>
0
);
(
vtmove
[
i
].
v
acpage
->
offsets_used
)
--
;
}
num_vtmove
=
0
;
elog
(
NOTICE
,
"Too old parent tuple found - can't continue repair_frag"
);
...
...
@@ -1531,7 +1531,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
ItemPointerSetInvalid
(
&
Ctid
);
for
(
ti
=
0
;
ti
<
num_vtmove
;
ti
++
)
{
V
PageDescr
destvpd
=
vtmove
[
ti
].
vpd
;
V
acPage
destvacpage
=
vtmove
[
ti
].
vacpage
;
/* Get tuple from chain */
tuple
.
t_self
=
vtmove
[
ti
].
tid
;
...
...
@@ -1544,7 +1544,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
tuple
.
t_data
=
(
HeapTupleHeader
)
PageGetItem
(
Cpage
,
Citemid
);
tuple_len
=
tuple
.
t_len
=
ItemIdGetLength
(
Citemid
);
/* Get page to move in */
cur_buffer
=
ReadBuffer
(
onerel
,
destv
pd
->
vpd_
blkno
);
cur_buffer
=
ReadBuffer
(
onerel
,
destv
acpage
->
blkno
);
/*
* We should LockBuffer(cur_buffer) but don't, at the
...
...
@@ -1559,20 +1559,20 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
*
* This path is different from the other callers of
* vacuum_page, because we have already incremented the
* v
pd's vpd_
offsets_used field to account for the
* v
acpage's
offsets_used field to account for the
* tuple(s) we expect to move onto the page. Therefore
* vacuum_page's check for
vpd_
offsets_used == 0 is
* vacuum_page's check for offsets_used == 0 is
* wrong. But since that's a good debugging check for
* all other callers, we work around it here rather
* than remove it.
*/
if
(
!
PageIsEmpty
(
ToPage
)
&&
vtmove
[
ti
].
cleanVpd
)
{
int
sv_offsets_used
=
destv
pd
->
vpd_
offsets_used
;
int
sv_offsets_used
=
destv
acpage
->
offsets_used
;
destv
pd
->
vpd_
offsets_used
=
0
;
vacuum_page
(
ToPage
,
destv
pd
);
destv
pd
->
vpd_
offsets_used
=
sv_offsets_used
;
destv
acpage
->
offsets_used
=
0
;
vacuum_page
(
ToPage
,
destv
acpage
);
destv
acpage
->
offsets_used
=
sv_offsets_used
;
}
heap_copytuple_with_tuple
(
&
tuple
,
&
newtup
);
RelationInvalidateHeapTuple
(
onerel
,
&
tuple
);
...
...
@@ -1585,15 +1585,15 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if
(
newoff
==
InvalidOffsetNumber
)
{
elog
(
ERROR
,
"moving chain: failed to add item with len = %u to page %u"
,
tuple_len
,
destv
pd
->
vpd_
blkno
);
tuple_len
,
destv
acpage
->
blkno
);
}
newitemid
=
PageGetItemId
(
ToPage
,
newoff
);
pfree
(
newtup
.
t_data
);
newtup
.
t_datamcxt
=
NULL
;
newtup
.
t_data
=
(
HeapTupleHeader
)
PageGetItem
(
ToPage
,
newitemid
);
ItemPointerSet
(
&
(
newtup
.
t_self
),
destv
pd
->
vpd_
blkno
,
newoff
);
if
(((
int
)
destv
pd
->
vpd_
blkno
)
>
last_move_dest_block
)
last_move_dest_block
=
destv
pd
->
vpd_
blkno
;
ItemPointerSet
(
&
(
newtup
.
t_self
),
destv
acpage
->
blkno
,
newoff
);
if
(((
int
)
destv
acpage
->
blkno
)
>
last_move_dest_block
)
last_move_dest_block
=
destv
acpage
->
blkno
;
/*
* Set t_ctid pointing to itself for last tuple in
...
...
@@ -1617,7 +1617,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* (corresponding index tuple will be cleaned).
*/
if
(
Cbuf
==
buf
)
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
ItemPointerGetOffsetNumber
(
&
(
tuple
.
t_self
));
else
keep_tuples
++
;
...
...
@@ -1670,25 +1670,25 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if
(
!
enough_space
(
cur_page
,
vacrelstats
->
min_tlen
))
{
Assert
(
num_fraged_pages
>
cur_item
);
memmove
(
fraged_pages
->
vpl_
pagedesc
+
cur_item
,
fraged_pages
->
vpl_
pagedesc
+
cur_item
+
1
,
sizeof
(
V
PageDescr
)
*
(
num_fraged_pages
-
cur_item
-
1
));
memmove
(
fraged_pages
->
pagedesc
+
cur_item
,
fraged_pages
->
pagedesc
+
cur_item
+
1
,
sizeof
(
V
acPage
)
*
(
num_fraged_pages
-
cur_item
-
1
));
num_fraged_pages
--
;
}
}
for
(
i
=
0
;
i
<
num_fraged_pages
;
i
++
)
{
if
(
enough_space
(
fraged_pages
->
vpl_
pagedesc
[
i
],
tuple_len
))
if
(
enough_space
(
fraged_pages
->
pagedesc
[
i
],
tuple_len
))
break
;
}
if
(
i
==
num_fraged_pages
)
break
;
/* can't move item anywhere */
cur_item
=
i
;
cur_page
=
fraged_pages
->
vpl_
pagedesc
[
cur_item
];
cur_buffer
=
ReadBuffer
(
onerel
,
cur_page
->
vpd_
blkno
);
cur_page
=
fraged_pages
->
pagedesc
[
cur_item
];
cur_buffer
=
ReadBuffer
(
onerel
,
cur_page
->
blkno
);
ToPage
=
BufferGetPage
(
cur_buffer
);
/* if this page was not used before - clean it */
if
(
!
PageIsEmpty
(
ToPage
)
&&
cur_page
->
vpd_
offsets_used
==
0
)
if
(
!
PageIsEmpty
(
ToPage
)
&&
cur_page
->
offsets_used
==
0
)
vacuum_page
(
ToPage
,
cur_page
);
}
...
...
@@ -1713,14 +1713,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
{
elog
(
ERROR
,
"\
failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)"
,
tuple_len
,
cur_page
->
vpd_blkno
,
cur_page
->
vpd_
free
,
cur_page
->
vpd_offsets_used
,
cur_page
->
vpd_
offsets_free
);
tuple_len
,
cur_page
->
blkno
,
cur_page
->
free
,
cur_page
->
offsets_used
,
cur_page
->
offsets_free
);
}
newitemid
=
PageGetItemId
(
ToPage
,
newoff
);
pfree
(
newtup
.
t_data
);
newtup
.
t_datamcxt
=
NULL
;
newtup
.
t_data
=
(
HeapTupleHeader
)
PageGetItem
(
ToPage
,
newitemid
);
ItemPointerSet
(
&
(
newtup
.
t_data
->
t_ctid
),
cur_page
->
vpd_
blkno
,
newoff
);
ItemPointerSet
(
&
(
newtup
.
t_data
->
t_ctid
),
cur_page
->
blkno
,
newoff
);
newtup
.
t_self
=
newtup
.
t_data
->
t_ctid
;
/*
...
...
@@ -1732,13 +1732,13 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
~
(
HEAP_XMIN_COMMITTED
|
HEAP_XMIN_INVALID
|
HEAP_MOVED_IN
);
tuple
.
t_data
->
t_infomask
|=
HEAP_MOVED_OFF
;
cur_page
->
vpd_
offsets_used
++
;
cur_page
->
offsets_used
++
;
num_moved
++
;
cur_page
->
vpd_
free
=
((
PageHeader
)
ToPage
)
->
pd_upper
-
((
PageHeader
)
ToPage
)
->
pd_lower
;
if
(((
int
)
cur_page
->
vpd_
blkno
)
>
last_move_dest_block
)
last_move_dest_block
=
cur_page
->
vpd_
blkno
;
cur_page
->
free
=
((
PageHeader
)
ToPage
)
->
pd_upper
-
((
PageHeader
)
ToPage
)
->
pd_lower
;
if
(((
int
)
cur_page
->
blkno
)
>
last_move_dest_block
)
last_move_dest_block
=
cur_page
->
blkno
;
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
offnum
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
offnum
;
/* insert index' tuples if needed */
if
(
Irel
!=
(
Relation
*
)
NULL
)
...
...
@@ -1788,22 +1788,22 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
/* some chains was moved while */
if
(
chain_tuple_moved
)
{
/* cleaning this page */
Assert
(
v
pc
->
vpd_
offsets_free
>
0
);
for
(
i
=
0
;
i
<
v
pc
->
vpd_
offsets_free
;
i
++
)
Assert
(
v
acpage
->
offsets_free
>
0
);
for
(
i
=
0
;
i
<
v
acpage
->
offsets_free
;
i
++
)
{
if
(
v
pc
->
vpd_
offsets
[
i
]
==
off
)
if
(
v
acpage
->
offsets
[
i
]
==
off
)
break
;
}
if
(
i
>=
v
pc
->
vpd_
offsets_free
)
/* not found */
if
(
i
>=
v
acpage
->
offsets_free
)
/* not found */
{
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
off
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
off
;
Assert
(
keep_tuples
>
0
);
keep_tuples
--
;
}
}
else
{
v
pc
->
vpd_offsets
[
vpc
->
vpd_
offsets_free
++
]
=
off
;
v
acpage
->
offsets
[
vacpage
->
offsets_free
++
]
=
off
;
Assert
(
keep_tuples
>
0
);
keep_tuples
--
;
}
...
...
@@ -1811,14 +1811,14 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
}
}
if
(
v
pc
->
vpd_
offsets_free
>
0
)
/* some tuples were moved */
if
(
v
acpage
->
offsets_free
>
0
)
/* some tuples were moved */
{
if
(
chain_tuple_moved
)
/* else - they are ordered */
{
qsort
((
char
*
)
(
v
pc
->
vpd_offsets
),
vpc
->
vpd_
offsets_free
,
qsort
((
char
*
)
(
v
acpage
->
offsets
),
vacpage
->
offsets_free
,
sizeof
(
OffsetNumber
),
vac_cmp_offno
);
}
reap_page
(
&
Nv
pl
,
vpc
);
reap_page
(
&
Nv
acpagelist
,
vacpage
);
WriteBuffer
(
buf
);
}
else
if
(
dowrite
)
...
...
@@ -1858,15 +1858,15 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
* xmin committed for inserted tuples
*/
checked_moved
=
0
;
for
(
i
=
0
,
vpp
=
vacuum_pages
->
vpl_pagedesc
;
i
<
vacuumed_pages
;
i
++
,
vpp
++
)
for
(
i
=
0
,
curpage
=
vacuum_pages
->
pagedesc
;
i
<
vacuumed_pages
;
i
++
,
curpage
++
)
{
Assert
((
*
vpp
)
->
vpd_
blkno
<
(
BlockNumber
)
blkno
);
buf
=
ReadBuffer
(
onerel
,
(
*
vpp
)
->
vpd_
blkno
);
Assert
((
*
curpage
)
->
blkno
<
(
BlockNumber
)
blkno
);
buf
=
ReadBuffer
(
onerel
,
(
*
curpage
)
->
blkno
);
page
=
BufferGetPage
(
buf
);
if
((
*
vpp
)
->
vpd_
offsets_used
==
0
)
/* this page was not used */
if
((
*
curpage
)
->
offsets_used
==
0
)
/* this page was not used */
{
if
(
!
PageIsEmpty
(
page
))
vacuum_page
(
page
,
*
vpp
);
vacuum_page
(
page
,
*
curpage
);
}
else
/* this page was used */
...
...
@@ -1897,7 +1897,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
elog
(
ERROR
,
"HEAP_MOVED_OFF/HEAP_MOVED_IN was expected"
);
}
}
Assert
((
*
vpp
)
->
vpd_
offsets_used
==
num_tuples
);
Assert
((
*
curpage
)
->
offsets_used
==
num_tuples
);
checked_moved
+=
num_tuples
;
}
WriteBuffer
(
buf
);
...
...
@@ -1909,18 +1909,18 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
nblocks
,
blkno
,
num_moved
,
show_rusage
(
&
ru0
));
if
(
Nv
pl
.
vpl_
num_pages
>
0
)
if
(
Nv
acpagelist
.
num_pages
>
0
)
{
/* vacuum indices again if needed */
if
(
Irel
!=
(
Relation
*
)
NULL
)
{
V
PageDescr
*
vpleft
,
V
acPage
*
vpleft
,
*
vpright
,
vpsave
;
/* re-sort Nv
pl.vpl_
pagedesc */
for
(
vpleft
=
Nv
pl
.
vpl_
pagedesc
,
vpright
=
Nv
pl
.
vpl_pagedesc
+
Nvpl
.
vpl_
num_pages
-
1
;
/* re-sort Nv
acpagelist.
pagedesc */
for
(
vpleft
=
Nv
acpagelist
.
pagedesc
,
vpright
=
Nv
acpagelist
.
pagedesc
+
Nvacpagelist
.
num_pages
-
1
;
vpleft
<
vpright
;
vpleft
++
,
vpright
--
)
{
vpsave
=
*
vpleft
;
...
...
@@ -1929,15 +1929,15 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
}
Assert
(
keep_tuples
>=
0
);
for
(
i
=
0
;
i
<
nindices
;
i
++
)
vacuum_index
(
&
Nv
pl
,
Irel
[
i
],
vacuum_index
(
&
Nv
acpagelist
,
Irel
[
i
],
vacrelstats
->
num_tuples
,
keep_tuples
);
}
/* clean moved tuples from last page in Nv
pl
list */
if
(
v
pc
->
vpd_
blkno
==
(
BlockNumber
)
(
blkno
-
1
)
&&
v
pc
->
vpd_
offsets_free
>
0
)
/* clean moved tuples from last page in Nv
acpagelist
list */
if
(
v
acpage
->
blkno
==
(
BlockNumber
)
(
blkno
-
1
)
&&
v
acpage
->
offsets_free
>
0
)
{
buf
=
ReadBuffer
(
onerel
,
v
pc
->
vpd_
blkno
);
buf
=
ReadBuffer
(
onerel
,
v
acpage
->
blkno
);
page
=
BufferGetPage
(
buf
);
num_tuples
=
0
;
for
(
offnum
=
FirstOffsetNumber
;
...
...
@@ -1964,16 +1964,16 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
}
}
Assert
(
v
pc
->
vpd_
offsets_free
==
num_tuples
);
Assert
(
v
acpage
->
offsets_free
==
num_tuples
);
PageRepairFragmentation
(
page
);
WriteBuffer
(
buf
);
}
/* now - free new list of reaped pages */
vpp
=
Nvpl
.
vpl_
pagedesc
;
for
(
i
=
0
;
i
<
Nv
pl
.
vpl_num_pages
;
i
++
,
vpp
++
)
pfree
(
*
vpp
);
pfree
(
Nv
pl
.
vpl_
pagedesc
);
curpage
=
Nvacpagelist
.
pagedesc
;
for
(
i
=
0
;
i
<
Nv
acpagelist
.
num_pages
;
i
++
,
curpage
++
)
pfree
(
*
curpage
);
pfree
(
Nv
acpagelist
.
pagedesc
);
}
/* truncate relation, after flushing any dirty pages out to disk */
...
...
@@ -1995,7 +1995,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
close_indices
(
nindices
,
Irel
);
}
pfree
(
v
pc
);
pfree
(
v
acpage
);
if
(
vacrelstats
->
vtlinks
!=
NULL
)
pfree
(
vacrelstats
->
vtlinks
);
...
...
@@ -2008,34 +2008,34 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
* if there are "empty" end-blocks.
*/
static
void
vacuum_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
vacuum_pages
)
vacuum_heap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
V
ac
PageList
vacuum_pages
)
{
Buffer
buf
;
Page
page
;
V
PageDescr
*
vpp
;
V
acPage
*
vacpage
;
int
nblocks
;
int
i
;
nblocks
=
vacuum_pages
->
vpl_
num_pages
;
nblocks
-=
vacuum_pages
->
vpl_
empty_end_pages
;
/* nothing to do with
nblocks
=
vacuum_pages
->
num_pages
;
nblocks
-=
vacuum_pages
->
empty_end_pages
;
/* nothing to do with
* them */
for
(
i
=
0
,
v
pp
=
vacuum_pages
->
vpl_pagedesc
;
i
<
nblocks
;
i
++
,
vpp
++
)
for
(
i
=
0
,
v
acpage
=
vacuum_pages
->
pagedesc
;
i
<
nblocks
;
i
++
,
vacpage
++
)
{
if
((
*
v
pp
)
->
vpd_
offsets_free
>
0
)
if
((
*
v
acpage
)
->
offsets_free
>
0
)
{
buf
=
ReadBuffer
(
onerel
,
(
*
v
pp
)
->
vpd_
blkno
);
buf
=
ReadBuffer
(
onerel
,
(
*
v
acpage
)
->
blkno
);
page
=
BufferGetPage
(
buf
);
vacuum_page
(
page
,
*
v
pp
);
vacuum_page
(
page
,
*
v
acpage
);
WriteBuffer
(
buf
);
}
}
/* truncate relation if there are some empty end-pages */
if
(
vacuum_pages
->
vpl_
empty_end_pages
>
0
)
if
(
vacuum_pages
->
empty_end_pages
>
0
)
{
Assert
(
vacrelstats
->
num_pages
>=
vacuum_pages
->
vpl_
empty_end_pages
);
nblocks
=
vacrelstats
->
num_pages
-
vacuum_pages
->
vpl_
empty_end_pages
;
Assert
(
vacrelstats
->
num_pages
>=
vacuum_pages
->
empty_end_pages
);
nblocks
=
vacrelstats
->
num_pages
-
vacuum_pages
->
empty_end_pages
;
elog
(
MESSAGE_LEVEL
,
"Rel %s: Pages: %u --> %u."
,
RelationGetRelationName
(
onerel
),
vacrelstats
->
num_pages
,
nblocks
);
...
...
@@ -2065,17 +2065,17 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages)
* and repair its fragmentation.
*/
static
void
vacuum_page
(
Page
page
,
V
PageDescr
vpd
)
vacuum_page
(
Page
page
,
V
acPage
vacpage
)
{
ItemId
itemid
;
int
i
;
/* There shouldn't be any tuples moved onto the page yet! */
Assert
(
v
pd
->
vpd_
offsets_used
==
0
);
Assert
(
v
acpage
->
offsets_used
==
0
);
for
(
i
=
0
;
i
<
v
pd
->
vpd_
offsets_free
;
i
++
)
for
(
i
=
0
;
i
<
v
acpage
->
offsets_free
;
i
++
)
{
itemid
=
&
(((
PageHeader
)
page
)
->
pd_linp
[
v
pd
->
vpd_
offsets
[
i
]
-
1
]);
itemid
=
&
(((
PageHeader
)
page
)
->
pd_linp
[
v
acpage
->
offsets
[
i
]
-
1
]);
itemid
->
lp_flags
&=
~
LP_USED
;
}
PageRepairFragmentation
(
page
);
...
...
@@ -2128,7 +2128,7 @@ scan_index(Relation indrel, int num_tuples)
/*
* vacuum_index() -- vacuum one index relation.
*
* Vpl is the VPageList of the heap we're currently vacuuming.
* Vpl is the V
ac
PageList of the heap we're currently vacuuming.
* It's locked. Indrel is an index relation on the vacuumed heap.
* We don't set locks on the index relation here, since the indexed
* access methods support locking at different granularities.
...
...
@@ -2138,7 +2138,7 @@ scan_index(Relation indrel, int num_tuples)
* pg_class.
*/
static
void
vacuum_index
(
V
PageList
vpl
,
Relation
indrel
,
int
num_tuples
,
int
keep_tuples
)
vacuum_index
(
V
acPageList
vacpagelist
,
Relation
indrel
,
int
num_tuples
,
int
keep_tuples
)
{
RetrieveIndexResult
res
;
IndexScanDesc
iscan
;
...
...
@@ -2146,7 +2146,7 @@ vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples)
int
tups_vacuumed
;
int
num_index_tuples
;
int
num_pages
;
V
PageDescr
vp
;
V
acPage
vp
;
struct
rusage
ru0
;
getrusage
(
RUSAGE_SELF
,
&
ru0
);
...
...
@@ -2161,7 +2161,7 @@ vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples)
{
heapptr
=
&
res
->
heap_iptr
;
if
((
vp
=
tid_reaped
(
heapptr
,
v
pl
))
!=
(
VPageDescr
)
NULL
)
if
((
vp
=
tid_reaped
(
heapptr
,
v
acpagelist
))
!=
(
VacPage
)
NULL
)
{
#ifdef NOT_USED
elog
(
DEBUG
,
"<%x,%x> -> <%x,%x>"
,
...
...
@@ -2170,11 +2170,11 @@ vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples)
ItemPointerGetBlockNumber
(
&
(
res
->
heap_iptr
)),
ItemPointerGetOffsetNumber
(
&
(
res
->
heap_iptr
)));
#endif
if
(
vp
->
vpd_
offsets_free
==
0
)
if
(
vp
->
offsets_free
==
0
)
{
elog
(
NOTICE
,
"Index %s: pointer to EmptyPage (blk %u off %u) - fixing"
,
RelationGetRelationName
(
indrel
),
vp
->
vpd_
blkno
,
ItemPointerGetOffsetNumber
(
heapptr
));
vp
->
blkno
,
ItemPointerGetOffsetNumber
(
heapptr
));
}
++
tups_vacuumed
;
index_delete
(
indrel
,
&
res
->
index_iptr
);
...
...
@@ -2206,42 +2206,42 @@ vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples)
/*
* tid_reaped() -- is a particular tid reaped?
*
* v
pl->VPageDescr
_array is sorted in right order.
* v
acpagelist->VacPage
_array is sorted in right order.
*/
static
V
PageDescr
tid_reaped
(
ItemPointer
itemptr
,
V
PageList
vpl
)
static
V
acPage
tid_reaped
(
ItemPointer
itemptr
,
V
acPageList
vacpagelist
)
{
OffsetNumber
ioffno
;
OffsetNumber
*
voff
;
V
PageDescr
vp
,
V
acPage
vp
,
*
vpp
;
V
PageDescrData
vpd
;
V
acPageData
vacpage
;
v
pd
.
vpd_
blkno
=
ItemPointerGetBlockNumber
(
itemptr
);
v
acpage
.
blkno
=
ItemPointerGetBlockNumber
(
itemptr
);
ioffno
=
ItemPointerGetOffsetNumber
(
itemptr
);
vp
=
&
v
pd
;
vpp
=
(
V
PageDescr
*
)
vac_find_eq
((
void
*
)
(
vpl
->
vpl_
pagedesc
),
v
pl
->
vpl_num_pages
,
sizeof
(
VPageDescr
),
(
void
*
)
&
vp
,
vp
=
&
v
acpage
;
vpp
=
(
V
acPage
*
)
vac_find_eq
((
void
*
)
(
vacpagelist
->
pagedesc
),
v
acpagelist
->
num_pages
,
sizeof
(
VacPage
),
(
void
*
)
&
vp
,
vac_cmp_blk
);
if
(
vpp
==
(
V
PageDescr
*
)
NULL
)
return
(
V
PageDescr
)
NULL
;
if
(
vpp
==
(
V
acPage
*
)
NULL
)
return
(
V
acPage
)
NULL
;
vp
=
*
vpp
;
/* ok - we are on true page */
if
(
vp
->
vpd_
offsets_free
==
0
)
if
(
vp
->
offsets_free
==
0
)
{
/* this is EmptyPage !!! */
return
vp
;
}
voff
=
(
OffsetNumber
*
)
vac_find_eq
((
void
*
)
(
vp
->
vpd_
offsets
),
vp
->
vpd_
offsets_free
,
sizeof
(
OffsetNumber
),
(
void
*
)
&
ioffno
,
voff
=
(
OffsetNumber
*
)
vac_find_eq
((
void
*
)
(
vp
->
offsets
),
vp
->
offsets_free
,
sizeof
(
OffsetNumber
),
(
void
*
)
&
ioffno
,
vac_cmp_offno
);
if
(
voff
==
(
OffsetNumber
*
)
NULL
)
return
(
V
PageDescr
)
NULL
;
return
(
V
acPage
)
NULL
;
return
vp
;
...
...
@@ -2720,43 +2720,44 @@ del_stats(Oid relid, int attcnt, int *attnums)
* (and highest tid on a page is last).
*/
static
void
reap_page
(
V
PageList
vpl
,
VPageDescr
vpc
)
reap_page
(
V
acPageList
vacpagelist
,
VacPage
vacpage
)
{
V
PageDescr
newvpd
;
V
acPage
newvacpage
;
/* allocate a V
PageDescr
Data entry */
newv
pd
=
(
VPageDescr
)
palloc
(
sizeof
(
VPageDescrData
)
+
vpc
->
vpd_
offsets_free
*
sizeof
(
OffsetNumber
));
/* allocate a V
acPage
Data entry */
newv
acpage
=
(
VacPage
)
palloc
(
sizeof
(
VacPageData
)
+
vacpage
->
offsets_free
*
sizeof
(
OffsetNumber
));
/* fill it in */
if
(
v
pc
->
vpd_
offsets_free
>
0
)
memmove
(
newv
pd
->
vpd_offsets
,
vpc
->
vpd_offsets
,
vpc
->
vpd_
offsets_free
*
sizeof
(
OffsetNumber
));
newv
pd
->
vpd_blkno
=
vpc
->
vpd_
blkno
;
newv
pd
->
vpd_free
=
vpc
->
vpd_
free
;
newv
pd
->
vpd_offsets_used
=
vpc
->
vpd_
offsets_used
;
newv
pd
->
vpd_offsets_free
=
vpc
->
vpd_
offsets_free
;
if
(
v
acpage
->
offsets_free
>
0
)
memmove
(
newv
acpage
->
offsets
,
vacpage
->
offsets
,
vacpage
->
offsets_free
*
sizeof
(
OffsetNumber
));
newv
acpage
->
blkno
=
vacpage
->
blkno
;
newv
acpage
->
free
=
vacpage
->
free
;
newv
acpage
->
offsets_used
=
vacpage
->
offsets_used
;
newv
acpage
->
offsets_free
=
vacpage
->
offsets_free
;
/* insert this page into v
pl
list */
vpage_insert
(
v
pl
,
newvpd
);
/* insert this page into v
acpagelist
list */
vpage_insert
(
v
acpagelist
,
newvacpage
);
}
static
void
vpage_insert
(
VPageList
vpl
,
VPageDescr
vpnew
)
static
void
vpage_insert
(
VacPageList
vacpagelist
,
VacPage
vpnew
)
{
#define PG_NPAGEDESC 1024
/* allocate a V
PageDescr
entry if needed */
if
(
v
pl
->
vpl_
num_pages
==
0
)
/* allocate a V
acPage
entry if needed */
if
(
v
acpagelist
->
num_pages
==
0
)
{
v
pl
->
vpl_pagedesc
=
(
VPageDescr
*
)
palloc
(
PG_NPAGEDESC
*
sizeof
(
VPageDescr
));
v
pl
->
vpl_
num_allocated_pages
=
PG_NPAGEDESC
;
v
acpagelist
->
pagedesc
=
(
VacPage
*
)
palloc
(
PG_NPAGEDESC
*
sizeof
(
VacPage
));
v
acpagelist
->
num_allocated_pages
=
PG_NPAGEDESC
;
}
else
if
(
v
pl
->
vpl_num_pages
>=
vpl
->
vpl_
num_allocated_pages
)
else
if
(
v
acpagelist
->
num_pages
>=
vacpagelist
->
num_allocated_pages
)
{
v
pl
->
vpl_
num_allocated_pages
*=
2
;
v
pl
->
vpl_pagedesc
=
(
VPageDescr
*
)
repalloc
(
vpl
->
vpl_pagedesc
,
vpl
->
vpl_num_allocated_pages
*
sizeof
(
VPageDescr
));
v
acpagelist
->
num_allocated_pages
*=
2
;
v
acpagelist
->
pagedesc
=
(
VacPage
*
)
repalloc
(
vacpagelist
->
pagedesc
,
vacpagelist
->
num_allocated_pages
*
sizeof
(
VacPage
));
}
v
pl
->
vpl_pagedesc
[
vpl
->
vpl_
num_pages
]
=
vpnew
;
(
v
pl
->
vpl_
num_pages
)
++
;
v
acpagelist
->
pagedesc
[
vacpagelist
->
num_pages
]
=
vpnew
;
(
v
acpagelist
->
num_pages
)
++
;
}
...
...
@@ -2821,8 +2822,8 @@ vac_cmp_blk(const void *left, const void *right)
BlockNumber
lblk
,
rblk
;
lblk
=
(
*
((
V
PageDescr
*
)
left
))
->
vpd_
blkno
;
rblk
=
(
*
((
V
PageDescr
*
)
right
))
->
vpd_
blkno
;
lblk
=
(
*
((
V
acPage
*
)
left
))
->
blkno
;
rblk
=
(
*
((
V
acPage
*
)
right
))
->
blkno
;
if
(
lblk
<
rblk
)
return
-
1
;
...
...
@@ -3063,20 +3064,20 @@ get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc)
static
bool
enough_space
(
V
PageDescr
vpd
,
Size
len
)
enough_space
(
V
acPage
vacpage
,
Size
len
)
{
len
=
MAXALIGN
(
len
);
if
(
len
>
v
pd
->
vpd_
free
)
if
(
len
>
v
acpage
->
free
)
return
false
;
if
(
v
pd
->
vpd_offsets_used
<
vpd
->
vpd_
offsets_free
)
/* there are free
if
(
v
acpage
->
offsets_used
<
vacpage
->
offsets_free
)
/* there are free
* itemid(s) */
return
true
;
/* and len <= free_space */
/* ok. noff_usd >= noff_free and so we'll have to allocate new itemid */
if
(
len
+
MAXALIGN
(
sizeof
(
ItemIdData
))
<=
v
pd
->
vpd_
free
)
if
(
len
+
MAXALIGN
(
sizeof
(
ItemIdData
))
<=
v
acpage
->
free
)
return
true
;
return
false
;
...
...
src/include/commands/vacuum.h
View file @
6d5cba7c
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: vacuum.h,v 1.
29 2000/05/29 16:21:0
5 momjian Exp $
* $Id: vacuum.h,v 1.
30 2000/05/29 17:06:1
5 momjian Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -30,29 +30,29 @@ typedef struct VAttListData
typedef
VAttListData
*
VAttList
;
typedef
struct
V
PageDescr
Data
typedef
struct
V
acPage
Data
{
BlockNumber
vpd_
blkno
;
/* BlockNumber of this Page */
Size
vpd_
free
;
/* FreeSpace on this Page */
uint16
vpd_
offsets_used
;
/* Number of OffNums used by
BlockNumber
blkno
;
/* BlockNumber of this Page */
Size
free
;
/* FreeSpace on this Page */
uint16
offsets_used
;
/* Number of OffNums used by
* vacuum */
uint16
vpd_
offsets_free
;
/* Number of OffNums free or to be
uint16
offsets_free
;
/* Number of OffNums free or to be
* free */
OffsetNumber
vpd_
offsets
[
1
];
/* Array of its OffNums */
}
V
PageDescr
Data
;
OffsetNumber
offsets
[
1
];
/* Array of its OffNums */
}
V
acPage
Data
;
typedef
V
PageDescrData
*
VPageDescr
;
typedef
V
acPageData
*
VacPage
;
typedef
struct
VPageListData
typedef
struct
V
ac
PageListData
{
int
vpl_
empty_end_pages
;
/* Number of "empty" end-pages */
int
vpl_num_pages
;
/* Number of pages in vpl_
pagedesc */
int
vpl_
num_allocated_pages
;
/* Number of allocated
* pages in
vpl_
pagedesc */
V
PageDescr
*
vpl_
pagedesc
;
/* Descriptions of pages */
}
VPageListData
;
int
empty_end_pages
;
/* Number of "empty" end-pages */
int
num_pages
;
/* Number of pages in
pagedesc */
int
num_allocated_pages
;
/* Number of allocated
* pages in pagedesc */
V
acPage
*
pagedesc
;
/* Descriptions of pages */
}
V
ac
PageListData
;
typedef
V
PageListData
*
V
PageList
;
typedef
V
acPageListData
*
Vac
PageList
;
typedef
struct
{
...
...
@@ -111,8 +111,8 @@ typedef VTupleLinkData *VTupleLink;
typedef
struct
VTupleMoveData
{
ItemPointerData
tid
;
/* tuple ID */
V
PageDescr
vpd
;
/* where to move */
bool
cleanVpd
;
/* clean v
pd
before using */
V
acPage
vacpage
;
/* where to move */
bool
cleanVpd
;
/* clean v
acpage
before using */
}
VTupleMoveData
;
typedef
VTupleMoveData
*
VTupleMove
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment