@ -36,10 +36,12 @@
# include "catalog/objectaccess.h"
# include "catalog/toasting.h"
# include "commands/cluster.h"
# include "commands/progress.h"
# include "commands/tablecmds.h"
# include "commands/vacuum.h"
# include "miscadmin.h"
# include "optimizer/optimizer.h"
# include "pgstat.h"
# include "storage/bufmgr.h"
# include "storage/lmgr.h"
# include "storage/predicate.h"
@ -276,6 +278,14 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
/* Check for user-requested abort. */
CHECK_FOR_INTERRUPTS ( ) ;
pgstat_progress_start_command ( PROGRESS_COMMAND_CLUSTER , tableOid ) ;
if ( OidIsValid ( indexOid ) )
pgstat_progress_update_param ( PROGRESS_CLUSTER_COMMAND ,
PROGRESS_CLUSTER_COMMAND_CLUSTER ) ;
else
pgstat_progress_update_param ( PROGRESS_CLUSTER_COMMAND ,
PROGRESS_CLUSTER_COMMAND_VACUUM_FULL ) ;
/*
* We grab exclusive access to the target rel and index for the duration
* of the transaction . ( This is redundant for the single - transaction
@ -286,7 +296,10 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
/* If the table has gone away, we can skip processing it */
if ( ! OldHeap )
{
pgstat_progress_end_command ( ) ;
return ;
}
/*
* Since we may open a new transaction for each relation , we have to check
@ -305,6 +318,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
if ( ! pg_class_ownercheck ( tableOid , GetUserId ( ) ) )
{
relation_close ( OldHeap , AccessExclusiveLock ) ;
pgstat_progress_end_command ( ) ;
return ;
}
@ -319,6 +333,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
if ( RELATION_IS_OTHER_TEMP ( OldHeap ) )
{
relation_close ( OldHeap , AccessExclusiveLock ) ;
pgstat_progress_end_command ( ) ;
return ;
}
@ -330,6 +345,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
if ( ! SearchSysCacheExists1 ( RELOID , ObjectIdGetDatum ( indexOid ) ) )
{
relation_close ( OldHeap , AccessExclusiveLock ) ;
pgstat_progress_end_command ( ) ;
return ;
}
@ -340,6 +356,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
if ( ! HeapTupleIsValid ( tuple ) ) /* probably can't happen */
{
relation_close ( OldHeap , AccessExclusiveLock ) ;
pgstat_progress_end_command ( ) ;
return ;
}
indexForm = ( Form_pg_index ) GETSTRUCT ( tuple ) ;
@ -347,6 +364,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
{
ReleaseSysCache ( tuple ) ;
relation_close ( OldHeap , AccessExclusiveLock ) ;
pgstat_progress_end_command ( ) ;
return ;
}
ReleaseSysCache ( tuple ) ;
@ -401,6 +419,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
! RelationIsPopulated ( OldHeap ) )
{
relation_close ( OldHeap , AccessExclusiveLock ) ;
pgstat_progress_end_command ( ) ;
return ;
}
@ -416,6 +435,8 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
rebuild_relation ( OldHeap , indexOid , verbose ) ;
/* NB: rebuild_relation does table_close() on OldHeap */
pgstat_progress_end_command ( ) ;
}
/*
@ -928,6 +949,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
*/
if ( OldIndex ! = NULL & & ! use_sort )
{
const int ci_index [ ] = {
PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_INDEX_RELID
} ;
int64 ci_val [ 2 ] ;
/* Set phase and OIDOldIndex to columns */
ci_val [ 0 ] = PROGRESS_CLUSTER_PHASE_INDEX_SCAN_HEAP ;
ci_val [ 1 ] = OIDOldIndex ;
pgstat_progress_update_multi_param ( 2 , ci_index , ci_val ) ;
tableScan = NULL ;
heapScan = NULL ;
indexScan = index_beginscan ( OldHeap , OldIndex , SnapshotAny , 0 , 0 ) ;
@ -935,9 +967,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
}
else
{
/* In scan-and-sort mode and also VACUUM FULL, set phase */
pgstat_progress_update_param ( PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_PHASE_SEQ_SCAN_HEAP ) ;
tableScan = table_beginscan ( OldHeap , SnapshotAny , 0 , ( ScanKey ) NULL ) ;
heapScan = ( HeapScanDesc ) tableScan ;
indexScan = NULL ;
/* Set total heap blocks */
pgstat_progress_update_param ( PROGRESS_CLUSTER_TOTAL_HEAP_BLKS ,
heapScan - > rs_nblocks ) ;
}
slot = table_slot_create ( OldHeap , NULL ) ;
@ -994,6 +1034,10 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
break ;
buf = heapScan - > rs_cbuf ;
/* In scan-and-sort mode and also VACUUM FULL, set heap blocks scanned */
pgstat_progress_update_param ( PROGRESS_CLUSTER_HEAP_BLKS_SCANNED ,
heapScan - > rs_cblock + 1 ) ;
}
LockBuffer ( buf , BUFFER_LOCK_SHARE ) ;
@ -1064,12 +1108,31 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
num_tuples + = 1 ;
if ( tuplesort ! = NULL )
{
tuplesort_putheaptuple ( tuplesort , tuple ) ;
/* In scan-and-sort mode, report increase in number of tuples scanned */
pgstat_progress_update_param ( PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED ,
num_tuples ) ;
}
else
{
const int ct_index [ ] = {
PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED ,
PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN
} ;
int64 ct_val [ 2 ] ;
reform_and_rewrite_tuple ( tuple ,
oldTupDesc , newTupDesc ,
values , isnull ,
rwstate ) ;
/* In indexscan mode and also VACUUM FULL, report increase in number of tuples scanned and written */
ct_val [ 0 ] = num_tuples ;
ct_val [ 1 ] = num_tuples ;
pgstat_progress_update_multi_param ( 2 , ct_index , ct_val ) ;
}
}
if ( indexScan ! = NULL )
@ -1085,8 +1148,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
*/
if ( tuplesort ! = NULL )
{
double n_tuples = 0 ;
/* Report that we are now sorting tuples */
pgstat_progress_update_param ( PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_PHASE_SORT_TUPLES ) ;
tuplesort_performsort ( tuplesort ) ;
/* Report that we are now writing new heap */
pgstat_progress_update_param ( PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_PHASE_WRITE_NEW_HEAP ) ;
for ( ; ; )
{
HeapTuple tuple ;
@ -1097,10 +1169,14 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
if ( tuple = = NULL )
break ;
n_tuples + = 1 ;
reform_and_rewrite_tuple ( tuple ,
oldTupDesc , newTupDesc ,
values , isnull ,
rwstate ) ;
/* Report n_tuples */
pgstat_progress_update_param ( PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN ,
n_tuples ) ;
}
tuplesort_end ( tuplesort ) ;
@ -1539,6 +1615,10 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
int reindex_flags ;
int i ;
/* Report that we are now swapping relation files */
pgstat_progress_update_param ( PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_PHASE_SWAP_REL_FILES ) ;
/* Zero out possible results from swapped_relation_files */
memset ( mapped_tables , 0 , sizeof ( mapped_tables ) ) ;
@ -1586,8 +1666,16 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
else if ( newrelpersistence = = RELPERSISTENCE_PERMANENT )
reindex_flags | = REINDEX_REL_FORCE_INDEXES_PERMANENT ;
/* Report that we are now reindexing relations */
pgstat_progress_update_param ( PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_PHASE_REBUILD_INDEX ) ;
reindex_relation ( OIDOldHeap , reindex_flags , 0 ) ;
/* Report that we are now doing clean up */
pgstat_progress_update_param ( PROGRESS_CLUSTER_PHASE ,
PROGRESS_CLUSTER_PHASE_FINAL_CLEANUP ) ;
/*
* If the relation being rebuild is pg_class , swap_relation_files ( )
* couldn ' t update pg_class ' s own pg_class entry ( check comments in