track_nested_command_progress.patch
text/x-patch
Filename: track_nested_command_progress.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/postmaster/pgstat.c | 34 | 13 |
| src/backend/utils/adt/pgstatfuncs.c | 15 | 3 |
| src/include/pgstat.h | 23 | 11 |
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index d362e7f7d7..99e4844e6c 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3016,8 +3016,10 @@ pgstat_bestart(void)
#endif
lbeentry.st_state = STATE_UNDEFINED;
- lbeentry.st_progress_command = PROGRESS_COMMAND_INVALID;
- lbeentry.st_progress_command_target = InvalidOid;
+ MemSet(&(lbeentry.st_progress_cmds), 0,
+ sizeof(PgBackendProgressInfo) * PGSTAT_MAX_PROGRESS_INFO);
+ /* Set invalid command index */
+ lbeentry.st_current_cmd = -1;
/*
* we don't zero st_progress_param here to save cycles; nobody should
@@ -3203,10 +3205,22 @@ pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
if (!beentry || !pgstat_track_activities)
return;
+ Assert(beentry->st_current_cmd >= -1);
+
+ /* The given command is already started */
+ if (beentry->st_progress_cmds[beentry->st_current_cmd].command == cmdtype)
+ return;
+
+ /* The progress information queue is full */
+ if (beentry->st_current_cmd >= PGSTAT_MAX_PROGRESS_INFO - 1)
+ elog(ERROR, "progress information per backends is full");
+
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));
+ beentry->st_current_cmd++;
+ MemSet(&(beentry->st_progress_cmds[beentry->st_current_cmd]),
+ 0, sizeof(PgBackendProgressInfo));
+ beentry->st_progress_cmds[beentry->st_current_cmd].command = cmdtype;
+ beentry->st_progress_cmds[beentry->st_current_cmd].target = relid;
PGSTAT_END_WRITE_ACTIVITY(beentry);
}
@@ -3223,11 +3237,11 @@ pgstat_progress_update_param(int index, int64 val)
Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
- if (!beentry || !pgstat_track_activities)
+ if (!beentry || !pgstat_track_activities || beentry->st_current_cmd < 0)
return;
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
- beentry->st_progress_param[index] = val;
+ beentry->st_progress_cmds[beentry->st_current_cmd].params[index] = val;
PGSTAT_END_WRITE_ACTIVITY(beentry);
}
@@ -3245,7 +3259,8 @@ pgstat_progress_update_multi_param(int nparam, const int *index,
volatile PgBackendStatus *beentry = MyBEEntry;
int i;
- if (!beentry || !pgstat_track_activities || nparam == 0)
+ if (!beentry || !pgstat_track_activities || nparam == 0 ||
+ beentry->st_current_cmd < 0)
return;
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
@@ -3254,7 +3269,8 @@ pgstat_progress_update_multi_param(int nparam, const int *index,
{
Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM);
- beentry->st_progress_param[index[i]] = val[i];
+ beentry->st_progress_cmds[beentry->st_current_cmd].params[index[i]] =
+ val[i];
}
PGSTAT_END_WRITE_ACTIVITY(beentry);
@@ -3274,13 +3290,18 @@ pgstat_progress_end_command(void)
if (!beentry)
return;
- if (!pgstat_track_activities
- && beentry->st_progress_command == PROGRESS_COMMAND_INVALID)
+
+ if (!pgstat_track_activities || beentry->st_current_cmd < 0 ||
+ beentry->st_progress_cmds[beentry->st_current_cmd].command ==
+ PROGRESS_COMMAND_INVALID)
return;
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
- beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
- beentry->st_progress_command_target = InvalidOid;
+ beentry->st_progress_cmds[beentry->st_current_cmd].command =
+ PROGRESS_COMMAND_INVALID;
+ beentry->st_progress_cmds[beentry->st_current_cmd].target =
+ InvalidOid;
+ beentry->st_current_cmd--;
PGSTAT_END_WRITE_ACTIVITY(beentry);
}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 05240bfd14..76ae2e0115 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -495,6 +495,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
Datum values[PG_STAT_GET_PROGRESS_COLS];
bool nulls[PG_STAT_GET_PROGRESS_COLS];
int i;
+ int cmdidx;
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
@@ -510,7 +511,18 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
* Report values for only those backends which are running the given
* command.
*/
- if (!beentry || beentry->st_progress_command != cmdtype)
+ if (!beentry)
+ continue;
+
+ /* Look up the progress information of the given command */
+ for (cmdidx = 0; cmdidx <= beentry->st_current_cmd; cmdidx++)
+ {
+ if (beentry->st_progress_cmds[cmdidx].command == cmdtype)
+ break;
+ }
+
+ /* Skip if the command is not running */
+ if (cmdidx > beentry->st_current_cmd)
continue;
/* Value available to all callers */
@@ -520,9 +532,9 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
/* show rest of the values including relid only to role members */
if (has_privs_of_role(GetUserId(), beentry->st_userid))
{
- values[2] = ObjectIdGetDatum(beentry->st_progress_command_target);
+ values[2] = ObjectIdGetDatum(beentry->st_progress_cmds[cmdidx].target);
for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
- values[i + 3] = Int64GetDatum(beentry->st_progress_param[i]);
+ values[i + 3] = Int64GetDatum(beentry->st_progress_cmds[cmdidx].params[i]);
}
else
{
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index fe076d823d..b87f253777 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -953,13 +953,14 @@ typedef enum
*/
typedef enum ProgressCommandType
{
- PROGRESS_COMMAND_INVALID,
+ PROGRESS_COMMAND_INVALID = 0,
PROGRESS_COMMAND_VACUUM,
PROGRESS_COMMAND_CLUSTER,
PROGRESS_COMMAND_CREATE_INDEX
} ProgressCommandType;
#define PGSTAT_NUM_PROGRESS_PARAM 20
+#define PGSTAT_MAX_PROGRESS_INFO 4
/* ----------
* Shared-memory data structures
@@ -1010,6 +1011,18 @@ typedef struct PgBackendGSSStatus
} PgBackendGSSStatus;
+/*
+ * Struct for command progress information of one command. The 'target'
+ * should be the OID of the relation which the command targets (we assume
+ * there's just one, as this is meant for utility commands), but the
+ * meaning of each element in the params array is command-specific.
+ */
+typedef struct PgBackendProgressInfo
+{
+ ProgressCommandType command;
+ Oid target;
+ int64 params[PGSTAT_NUM_PROGRESS_PARAM];
+} PgBackendProgressInfo;
/* ----------
* PgBackendStatus
@@ -1085,17 +1098,16 @@ typedef struct PgBackendStatus
char *st_activity_raw;
/*
- * Command progress reporting. Any command which wishes can advertise
- * that it is running by setting st_progress_command,
- * st_progress_command_target, and st_progress_param[].
- * st_progress_command_target should be the OID of the relation which the
- * command targets (we assume there's just one, as this is meant for
- * utility commands), but the meaning of each element in the
- * st_progress_param array is command-specific.
+ * Command progress reporting. Since it's possible to nested call
+ * multiple commands that support progress report, e.g. CLUSTER
+ * executes REINDEX inside, we track progress of multiple commands.
+ * st_current_cmd is the index of st_progress_cmds of current executing
+ * command, -1 for invalid. Any command which wishes can advertise
+ * that is is running by increasing st_current_cmd and setting
+ * the corresponding elements of st_progress_cmd.
*/
- ProgressCommandType st_progress_command;
- Oid st_progress_command_target;
- int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
+ int st_current_cmd;
+ PgBackendProgressInfo st_progress_cmds[PGSTAT_MAX_PROGRESS_INFO];
} PgBackendStatus;
/*