Branch data Line data Source code
1 : : /* ----------
2 : : * backend_progress.c
3 : : *
4 : : * Command progress reporting infrastructure.
5 : : *
6 : : * Copyright (c) 2001-2026, PostgreSQL Global Development Group
7 : : *
8 : : * src/backend/utils/activity/backend_progress.c
9 : : * ----------
10 : : */
11 : : #include "postgres.h"
12 : :
13 : : #include "access/parallel.h"
14 : : #include "libpq/pqformat.h"
15 : : #include "storage/proc.h"
16 : : #include "utils/backend_progress.h"
17 : : #include "utils/backend_status.h"
18 : :
19 : :
20 : : /*-----------
21 : : * pgstat_progress_start_command() -
22 : : *
23 : : * Set st_progress_command (and st_progress_command_target) in own backend
24 : : * entry. Also, zero-initialize st_progress_param array.
25 : : *-----------
26 : : */
27 : : void
28 : 162579 : pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
29 : : {
30 : 162579 : volatile PgBackendStatus *beentry = MyBEEntry;
31 : :
32 [ + - - + ]: 162579 : if (!beentry || !pgstat_track_activities)
33 : 0 : return;
34 : :
35 : 162579 : PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
36 : 162579 : beentry->st_progress_command = cmdtype;
37 : 162579 : beentry->st_progress_command_target = relid;
38 [ + + ]: 3414159 : for (int i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
39 : 3251580 : beentry->st_progress_param[i] = 0;
40 : 162579 : PGSTAT_END_WRITE_ACTIVITY(beentry);
41 : : }
42 : :
43 : : /*-----------
44 : : * pgstat_progress_update_param() -
45 : : *
46 : : * Update index'th member in st_progress_param[] of own backend entry.
47 : : *-----------
48 : : */
49 : : void
50 : 14753177 : pgstat_progress_update_param(int index, int64 val)
51 : : {
52 : 14753177 : volatile PgBackendStatus *beentry = MyBEEntry;
53 : :
54 : : Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
55 : :
56 [ + - - + ]: 14753177 : if (!beentry || !pgstat_track_activities)
57 : 0 : return;
58 : :
59 : 14753177 : PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
60 : 14753177 : beentry->st_progress_param[index] = val;
61 : 14753177 : PGSTAT_END_WRITE_ACTIVITY(beentry);
62 : : }
63 : :
64 : : /*-----------
65 : : * pgstat_progress_incr_param() -
66 : : *
67 : : * Increment index'th member in st_progress_param[] of own backend entry.
68 : : *-----------
69 : : */
70 : : void
71 : 1975 : pgstat_progress_incr_param(int index, int64 incr)
72 : : {
73 : 1975 : volatile PgBackendStatus *beentry = MyBEEntry;
74 : :
75 : : Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
76 : :
77 [ + - - + ]: 1975 : if (!beentry || !pgstat_track_activities)
78 : 0 : return;
79 : :
80 : 1975 : PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
81 : 1975 : beentry->st_progress_param[index] += incr;
82 : 1975 : PGSTAT_END_WRITE_ACTIVITY(beentry);
83 : : }
84 : :
85 : : /*-----------
86 : : * pgstat_progress_parallel_incr_param() -
87 : : *
88 : : * A variant of pgstat_progress_incr_param to allow a worker to poke at
89 : : * a leader to do an incremental progress update.
90 : : *-----------
91 : : */
92 : : void
93 : 176 : pgstat_progress_parallel_incr_param(int index, int64 incr)
94 : : {
95 : : /*
96 : : * Parallel workers notify a leader through a PqParallelMsg_Progress
97 : : * message to update progress, passing the progress index and incremented
98 : : * value. Leaders can just call pgstat_progress_incr_param directly.
99 : : */
100 [ + + ]: 176 : if (IsParallelWorker())
101 : : {
102 : : static StringInfoData progress_message;
103 : :
104 : 9 : pq_beginmessage(&progress_message, PqParallelMsg_Progress);
105 : 9 : pq_sendint32(&progress_message, index);
106 : 9 : pq_sendint64(&progress_message, incr);
107 : 9 : pq_endmessage(&progress_message);
108 : : }
109 : : else
110 : 167 : pgstat_progress_incr_param(index, incr);
111 : 176 : }
112 : :
113 : : /*-----------
114 : : * pgstat_progress_update_multi_param() -
115 : : *
116 : : * Update multiple members in st_progress_param[] of own backend entry.
117 : : * This is atomic; readers won't see intermediate states.
118 : : *-----------
119 : : */
120 : : void
121 : 1122347 : pgstat_progress_update_multi_param(int nparam, const int *index,
122 : : const int64 *val)
123 : : {
124 : 1122347 : volatile PgBackendStatus *beentry = MyBEEntry;
125 : : int i;
126 : :
127 [ + - + - : 1122347 : if (!beentry || !pgstat_track_activities || nparam == 0)
- + ]
128 : 0 : return;
129 : :
130 : 1122347 : PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
131 : :
132 [ + + ]: 3324685 : for (i = 0; i < nparam; ++i)
133 : : {
134 : : Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM);
135 : :
136 : 2202338 : beentry->st_progress_param[index[i]] = val[i];
137 : : }
138 : :
139 : 1122347 : PGSTAT_END_WRITE_ACTIVITY(beentry);
140 : : }
141 : :
142 : : /*-----------
143 : : * pgstat_progress_end_command() -
144 : : *
145 : : * Reset st_progress_command (and st_progress_command_target) in own backend
146 : : * entry. This signals the end of the command.
147 : : *-----------
148 : : */
149 : : void
150 : 202525 : pgstat_progress_end_command(void)
151 : : {
152 : 202525 : volatile PgBackendStatus *beentry = MyBEEntry;
153 : :
154 [ + - - + ]: 202525 : if (!beentry || !pgstat_track_activities)
155 : 0 : return;
156 : :
157 [ + + ]: 202525 : if (beentry->st_progress_command == PROGRESS_COMMAND_INVALID)
158 : 40702 : return;
159 : :
160 : 161823 : PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
161 : 161823 : beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
162 : 161823 : beentry->st_progress_command_target = InvalidOid;
163 : 161823 : PGSTAT_END_WRITE_ACTIVITY(beentry);
164 : : }
|