PostgreSQL Source Code  git master
basebackup_progress.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * basebackup_progress.c
4  * Basebackup sink implementing progress tracking, including but not
5  * limited to command progress reporting.
6  *
7  * This should be used even if the PROGRESS option to the replication
8  * command BASE_BACKUP is not specified. Without that option, we won't
9  * have tallied up the size of the files that are going to need to be
10  * backed up, but we can still report to the command progress reporting
11  * facility how much data we've processed.
12  *
13  * Moreover, we also use this as a convenient place to update certain
14  * fields of the bbsink_state. That work is accurately described as
15  * keeping track of our progress, but it's not just for introspection.
16  * We need those fields to be updated properly in order for base backups
17  * to work.
18  *
19  * This particular basebackup sink requires extra callbacks that most base
20  * backup sinks don't. Rather than cramming those into the interface, we just
21  * have a few extra functions here that basebackup.c can call. (We could put
22  * the logic directly into that file as it's fairly simple, but it seems
23  * cleaner to have everything related to progress reporting in one place.)
24  *
25  * Portions Copyright (c) 2010-2023, PostgreSQL Global Development Group
26  *
27  * IDENTIFICATION
28  * src/backend/backup/basebackup_progress.c
29  *
30  *-------------------------------------------------------------------------
31  */
32 #include "postgres.h"
33 
34 #include "backup/basebackup.h"
35 #include "backup/basebackup_sink.h"
36 #include "commands/progress.h"
37 #include "miscadmin.h"
38 #include "pgstat.h"
39 #include "storage/latch.h"
40 #include "utils/timestamp.h"
41 
42 static void bbsink_progress_begin_backup(bbsink *sink);
43 static void bbsink_progress_archive_contents(bbsink *sink, size_t len);
44 static void bbsink_progress_end_archive(bbsink *sink);
45 
48  .begin_archive = bbsink_forward_begin_archive,
49  .archive_contents = bbsink_progress_archive_contents,
50  .end_archive = bbsink_progress_end_archive,
51  .begin_manifest = bbsink_forward_begin_manifest,
52  .manifest_contents = bbsink_forward_manifest_contents,
53  .end_manifest = bbsink_forward_end_manifest,
54  .end_backup = bbsink_forward_end_backup,
55  .cleanup = bbsink_forward_cleanup
56 };
57 
58 /*
59  * Create a new basebackup sink that performs progress tracking functions and
60  * forwards data to a successor sink.
61  */
62 bbsink *
63 bbsink_progress_new(bbsink *next, bool estimate_backup_size)
64 {
65  bbsink *sink;
66 
67  Assert(next != NULL);
68 
69  sink = palloc0(sizeof(bbsink));
70  *((const bbsink_ops **) &sink->bbs_ops) = &bbsink_progress_ops;
71  sink->bbs_next = next;
72 
73  /*
74  * Report that a base backup is in progress, and set the total size of the
75  * backup to -1, which will get translated to NULL. If we're estimating
76  * the backup size, we'll insert the real estimate when we have it.
77  */
80 
81  return sink;
82 }
83 
84 /*
85  * Progress reporting at start of backup.
86  */
87 static void
89 {
90  const int index[] = {
94  };
95  int64 val[3];
96 
97  /*
98  * Report that we are now streaming database files as a base backup. Also
99  * advertise the number of tablespaces, and, if known, the estimated total
100  * backup size.
101  */
103  if (sink->bbs_state->bytes_total_is_valid)
104  val[1] = sink->bbs_state->bytes_total;
105  else
106  val[1] = -1;
107  val[2] = list_length(sink->bbs_state->tablespaces);
109 
110  /* Delegate to next sink. */
112 }
113 
114 /*
115  * End-of archive progress reporting.
116  */
117 static void
119 {
120  /*
121  * We expect one archive per tablespace, so reaching the end of an archive
122  * also means reaching the end of a tablespace. (Some day we might have a
123  * reason to decouple these concepts.)
124  *
125  * If WAL is included in the backup, we'll mark the last tablespace
126  * complete before the last archive is complete, so we need a guard here
127  * to ensure that the number of tablespaces streamed doesn't exceed the
128  * total.
129  */
132  sink->bbs_state->tablespace_num + 1);
133 
134  /* Delegate to next sink. */
136 
137  /*
138  * This is a convenient place to update the bbsink_state's notion of which
139  * is the current tablespace. Note that the bbsink_state object is shared
140  * across all bbsink objects involved, but we're the outermost one and
141  * this is the very last thing we do.
142  */
143  sink->bbs_state->tablespace_num++;
144 }
145 
146 /*
147  * Handle progress tracking for new archive contents.
148  *
149  * Increment the counter for the amount of data already streamed
150  * by the given number of bytes, and update the progress report for
151  * pg_stat_progress_basebackup.
152  */
153 static void
155 {
156  bbsink_state *state = sink->bbs_state;
157  const int index[] = {
160  };
161  int64 val[2];
162  int nparam = 0;
163 
164  /* First update bbsink_state with # of bytes done. */
165  state->bytes_done += len;
166 
167  /* Now forward to next sink. */
169 
170  /* Prepare to set # of bytes done for command progress reporting. */
171  val[nparam++] = state->bytes_done;
172 
173  /*
174  * We may also want to update # of total bytes, to avoid overflowing past
175  * 100% or the full size. This may make the total size number change as we
176  * approach the end of the backup (the estimate will always be wrong if
177  * WAL is included), but that's better than having the done column be
178  * bigger than the total.
179  */
180  if (state->bytes_total_is_valid && state->bytes_done > state->bytes_total)
181  val[nparam++] = state->bytes_done;
182 
184 }
185 
186 /*
187  * Advertise that we are waiting for the start-of-backup checkpoint.
188  */
189 void
191 {
194 }
195 
196 /*
197  * Advertise that we are estimating the backup size.
198  */
199 void
201 {
204 }
205 
206 /*
207  * Advertise that we are waiting for WAL archiving at end-of-backup.
208  */
209 void
211 {
212  const int index[] = {
215  };
216  int64 val[2];
217 
218  /*
219  * We report having finished all tablespaces at this point, even if the
220  * archive for the main tablespace is still open, because what's going to
221  * be added is WAL files, not files that are really from the main
222  * tablespace.
223  */
225  val[1] = list_length(state->tablespaces);
227 }
228 
229 /*
230  * Advertise that we are transferring WAL files into the final archive.
231  */
232 void
234 {
237 }
238 
239 /*
240  * Advertise that we are no longer performing a backup.
241  */
242 void
244 {
246 }
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
void pgstat_progress_end_command(void)
@ PROGRESS_COMMAND_BASEBACKUP
static const bbsink_ops bbsink_progress_ops
void basebackup_progress_wait_checkpoint(void)
static void bbsink_progress_end_archive(bbsink *sink)
void basebackup_progress_wait_wal_archive(bbsink_state *state)
bbsink * bbsink_progress_new(bbsink *next, bool estimate_backup_size)
void basebackup_progress_done(void)
static void bbsink_progress_begin_backup(bbsink *sink)
static void bbsink_progress_archive_contents(bbsink *sink, size_t len)
void basebackup_progress_transfer_wal(void)
void basebackup_progress_estimate_backup_size(void)
void bbsink_forward_begin_backup(bbsink *sink)
void bbsink_forward_begin_manifest(bbsink *sink)
void bbsink_forward_end_backup(bbsink *sink, XLogRecPtr endptr, TimeLineID endtli)
void bbsink_forward_cleanup(bbsink *sink)
void bbsink_forward_manifest_contents(bbsink *sink, size_t len)
void bbsink_forward_end_archive(bbsink *sink)
void bbsink_forward_archive_contents(bbsink *sink, size_t len)
void bbsink_forward_begin_archive(bbsink *sink, const char *archive_name)
void bbsink_forward_end_manifest(bbsink *sink)
static int32 next
Definition: blutils.c:220
long val
Definition: informix.c:664
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc0(Size size)
Definition: mcxt.c:1257
const void size_t len
static int list_length(const List *l)
Definition: pg_list.h:152
#define InvalidOid
Definition: postgres_ext.h:36
#define PROGRESS_BASEBACKUP_PHASE_WAIT_WAL_ARCHIVE
Definition: progress.h:135
#define PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE
Definition: progress.h:133
#define PROGRESS_BASEBACKUP_BACKUP_TOTAL
Definition: progress.h:126
#define PROGRESS_BASEBACKUP_TBLSPC_TOTAL
Definition: progress.h:128
#define PROGRESS_BASEBACKUP_PHASE_STREAM_BACKUP
Definition: progress.h:134
#define PROGRESS_BASEBACKUP_PHASE_WAIT_CHECKPOINT
Definition: progress.h:132
#define PROGRESS_BASEBACKUP_TBLSPC_STREAMED
Definition: progress.h:129
#define PROGRESS_BASEBACKUP_PHASE
Definition: progress.h:125
#define PROGRESS_BASEBACKUP_PHASE_TRANSFER_WAL
Definition: progress.h:136
#define PROGRESS_BASEBACKUP_BACKUP_STREAMED
Definition: progress.h:127
void(* begin_backup)(bbsink *sink)
bool bytes_total_is_valid
uint64 bytes_total
List * tablespaces
bbsink * bbs_next
bbsink_state * bbs_state
const bbsink_ops * bbs_ops
Definition: type.h:95
Definition: regguts.h:323