mirror of
https://github.com/postgres/postgres.git
synced 2026-05-16 11:29:49 -04:00
The "partitions_total" and "partitions_done" fields were updated as though the current level of partitioning was the only one. In multi-level cases, not only could partitions_total change over the course of the command, but partitions_done could go backwards or exceed the currently-reported partitions_total. Fix by setting partitions_total to the total number of direct and indirect children once at command start, and then just incrementing partitions_done at appropriate points. Invent a new progress monitoring function "pgstat_progress_incr_param" to simplify doing the latter. We can avoid adding cost for the former when doing CREATE INDEX, because ProcessUtility already enumerates the children and it's pretty easy to pass the count down to DefineIndex. In principle the same could be done in ALTER TABLE, but that's structurally difficult; for now, just eat the cost of an extra find_all_inheritors scan in that case. Ilya Gladyshev and Justin Pryzby Discussion: https://postgr.es/m/a15f904a70924ffa4ca25c3c744cff31e0e6e143.camel@gmail.com
133 lines
3.2 KiB
C
133 lines
3.2 KiB
C
/* ----------
|
|
* backend_progress.c
|
|
*
|
|
* Command progress reporting infrastructure.
|
|
*
|
|
* Copyright (c) 2001-2023, PostgreSQL Global Development Group
|
|
*
|
|
* src/backend/utils/activity/backend_progress.c
|
|
* ----------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "port/atomics.h" /* for memory barriers */
|
|
#include "utils/backend_progress.h"
|
|
#include "utils/backend_status.h"
|
|
|
|
|
|
/*-----------
|
|
* pgstat_progress_start_command() -
|
|
*
|
|
* Set st_progress_command (and st_progress_command_target) in own backend
|
|
* entry. Also, zero-initialize st_progress_param array.
|
|
*-----------
|
|
*/
|
|
void
|
|
pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
|
|
{
|
|
volatile PgBackendStatus *beentry = MyBEEntry;
|
|
|
|
if (!beentry || !pgstat_track_activities)
|
|
return;
|
|
|
|
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
|
|
beentry->st_progress_command = cmdtype;
|
|
beentry->st_progress_command_target = relid;
|
|
MemSet(&beentry->st_progress_param, 0, sizeof(beentry->st_progress_param));
|
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
|
}
|
|
|
|
/*-----------
|
|
* pgstat_progress_update_param() -
|
|
*
|
|
* Update index'th member in st_progress_param[] of own backend entry.
|
|
*-----------
|
|
*/
|
|
void
|
|
pgstat_progress_update_param(int index, int64 val)
|
|
{
|
|
volatile PgBackendStatus *beentry = MyBEEntry;
|
|
|
|
Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
|
|
|
|
if (!beentry || !pgstat_track_activities)
|
|
return;
|
|
|
|
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
|
|
beentry->st_progress_param[index] = val;
|
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
|
}
|
|
|
|
/*-----------
|
|
* pgstat_progress_incr_param() -
|
|
*
|
|
* Increment index'th member in st_progress_param[] of own backend entry.
|
|
*-----------
|
|
*/
|
|
void
|
|
pgstat_progress_incr_param(int index, int64 incr)
|
|
{
|
|
volatile PgBackendStatus *beentry = MyBEEntry;
|
|
|
|
Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
|
|
|
|
if (!beentry || !pgstat_track_activities)
|
|
return;
|
|
|
|
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
|
|
beentry->st_progress_param[index] += incr;
|
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
|
}
|
|
|
|
/*-----------
|
|
* pgstat_progress_update_multi_param() -
|
|
*
|
|
* Update multiple members in st_progress_param[] of own backend entry.
|
|
* This is atomic; readers won't see intermediate states.
|
|
*-----------
|
|
*/
|
|
void
|
|
pgstat_progress_update_multi_param(int nparam, const int *index,
|
|
const int64 *val)
|
|
{
|
|
volatile PgBackendStatus *beentry = MyBEEntry;
|
|
int i;
|
|
|
|
if (!beentry || !pgstat_track_activities || nparam == 0)
|
|
return;
|
|
|
|
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
|
|
|
|
for (i = 0; i < nparam; ++i)
|
|
{
|
|
Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM);
|
|
|
|
beentry->st_progress_param[index[i]] = val[i];
|
|
}
|
|
|
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
|
}
|
|
|
|
/*-----------
|
|
* pgstat_progress_end_command() -
|
|
*
|
|
* Reset st_progress_command (and st_progress_command_target) in own backend
|
|
* entry. This signals the end of the command.
|
|
*-----------
|
|
*/
|
|
void
|
|
pgstat_progress_end_command(void)
|
|
{
|
|
volatile PgBackendStatus *beentry = MyBEEntry;
|
|
|
|
if (!beentry || !pgstat_track_activities)
|
|
return;
|
|
|
|
if (beentry->st_progress_command == PROGRESS_COMMAND_INVALID)
|
|
return;
|
|
|
|
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
|
|
beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
|
|
beentry->st_progress_command_target = InvalidOid;
|
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
|
}
|