diff options
Diffstat (limited to 'src/backend/replication/basebackup.c')
-rw-r--r-- | src/backend/replication/basebackup.c | 99 |
1 files changed, 97 insertions, 2 deletions
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index ca8bebf432b..f66cbc2428a 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -19,6 +19,7 @@ #include "access/xlog_internal.h" /* for pg_start/stop_backup */ #include "catalog/pg_type.h" #include "common/file_perm.h" +#include "commands/progress.h" #include "lib/stringinfo.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" @@ -70,6 +71,7 @@ static void parse_basebackup_options(List *options, basebackup_options *opt); static void SendXlogRecPtrResult(XLogRecPtr ptr, TimeLineID tli); static int compareWalFileNames(const ListCell *a, const ListCell *b); static void throttle(size_t increment); +static void update_basebackup_progress(int64 delta); static bool is_checksummed_file(const char *fullpath, const char *filename); /* Was the backup currently in-progress initiated in recovery mode? */ @@ -121,6 +123,12 @@ static long long int total_checksum_failures; /* Do not verify checksums. */ static bool noverify_checksums = false; +/* Total amount of backup data that will be streamed */ +static int64 backup_total = 0; + +/* Amount of backup data already streamed */ +static int64 backup_streamed = 0; + /* * Definition of one element part of an exclusion list, used for paths part * of checksum validation or base backups. "name" is the name of the file @@ -246,6 +254,10 @@ perform_base_backup(basebackup_options *opt) int datadirpathlen; List *tablespaces = NIL; + backup_total = 0; + backup_streamed = 0; + pgstat_progress_start_command(PROGRESS_COMMAND_BASEBACKUP, InvalidOid); + datadirpathlen = strlen(DataDir); backup_started_in_recovery = RecoveryInProgress(); @@ -255,6 +267,8 @@ perform_base_backup(basebackup_options *opt) total_checksum_failures = 0; + pgstat_progress_update_param(PROGRESS_BASEBACKUP_PHASE, + PROGRESS_BASEBACKUP_PHASE_WAIT_CHECKPOINT); startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli, labelfile, &tablespaces, tblspc_map_file, @@ -271,8 +285,7 @@ perform_base_backup(basebackup_options *opt) { ListCell *lc; tablespaceinfo *ti; - - SendXlogRecPtrResult(startptr, starttli); + int tblspc_streamed = 0; /* * Calculate the relative path of temporary statistics directory in @@ -291,6 +304,38 @@ perform_base_backup(basebackup_options *opt) ti->size = opt->progress ? sendDir(".", 1, true, tablespaces, true) : -1; tablespaces = lappend(tablespaces, ti); + /* + * Calculate the total backup size by summing up the size of each + * tablespace + */ + if (opt->progress) + { + foreach(lc, tablespaces) + { + tablespaceinfo *tmp = (tablespaceinfo *) lfirst(lc); + + backup_total += tmp->size; + } + } + + /* Report that we are now streaming database files as a base backup */ + { + const int index[] = { + PROGRESS_BASEBACKUP_PHASE, + PROGRESS_BASEBACKUP_BACKUP_TOTAL, + PROGRESS_BASEBACKUP_TBLSPC_TOTAL + }; + const int64 val[] = { + PROGRESS_BASEBACKUP_PHASE_STREAM_BACKUP, + backup_total, list_length(tablespaces) + }; + + pgstat_progress_update_multi_param(3, index, val); + } + + /* Send the starting position of the backup */ + SendXlogRecPtrResult(startptr, starttli); + /* Send tablespace header */ SendBackupHeader(tablespaces); @@ -372,8 +417,14 @@ perform_base_backup(basebackup_options *opt) } else pq_putemptymessage('c'); /* CopyDone */ + + tblspc_streamed++; + pgstat_progress_update_param(PROGRESS_BASEBACKUP_TBLSPC_STREAMED, + tblspc_streamed); } + pgstat_progress_update_param(PROGRESS_BASEBACKUP_PHASE, + PROGRESS_BASEBACKUP_PHASE_WAIT_WAL_ARCHIVE); endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli); } PG_END_ENSURE_ERROR_CLEANUP(do_pg_abort_backup, BoolGetDatum(false)); @@ -399,6 +450,9 @@ perform_base_backup(basebackup_options *opt) ListCell *lc; TimeLineID tli; + pgstat_progress_update_param(PROGRESS_BASEBACKUP_PHASE, + PROGRESS_BASEBACKUP_PHASE_TRANSFER_WAL); + /* * I'd rather not worry about timelines here, so scan pg_wal and * include all WAL files in the range between 'startptr' and 'endptr', @@ -548,6 +602,7 @@ perform_base_backup(basebackup_options *opt) if (pq_putmessage('d', buf, cnt)) ereport(ERROR, (errmsg("base backup could not send data, aborting backup"))); + update_basebackup_progress(cnt); len += cnt; throttle(cnt); @@ -623,6 +678,7 @@ perform_base_backup(basebackup_options *opt) errmsg("checksum verification failure during base backup"))); } + pgstat_progress_end_command(); } /* @@ -949,6 +1005,7 @@ sendFileWithContent(const char *filename, const char *content) _tarWriteHeader(filename, NULL, &statbuf, false); /* Send the contents as a CopyData message */ pq_putmessage('d', content, len); + update_basebackup_progress(len); /* Pad to 512 byte boundary, per tar format requirements */ pad = ((len + 511) & ~511) - len; @@ -958,6 +1015,7 @@ sendFileWithContent(const char *filename, const char *content) MemSet(buf, 0, pad); pq_putmessage('d', buf, pad); + update_basebackup_progress(pad); } } @@ -1565,6 +1623,7 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf if (pq_putmessage('d', buf, cnt)) ereport(ERROR, (errmsg("base backup could not send data, aborting backup"))); + update_basebackup_progress(cnt); len += cnt; throttle(cnt); @@ -1590,6 +1649,7 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf { cnt = Min(sizeof(buf), statbuf->st_size - len); pq_putmessage('d', buf, cnt); + update_basebackup_progress(cnt); len += cnt; throttle(cnt); } @@ -1604,6 +1664,7 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf { MemSet(buf, 0, pad); pq_putmessage('d', buf, pad); + update_basebackup_progress(pad); } FreeFile(fp); @@ -1658,6 +1719,7 @@ _tarWriteHeader(const char *filename, const char *linktarget, } pq_putmessage('d', h, sizeof(h)); + update_basebackup_progress(sizeof(h)); } return sizeof(h); @@ -1755,3 +1817,36 @@ throttle(size_t increment) */ throttled_last = GetCurrentTimestamp(); } + +/* + * Increment the counter for the amount of data already streamed + * by the given number of bytes, and update the progress report for + * pg_stat_progress_basebackup. + */ +static void +update_basebackup_progress(int64 delta) +{ + const int index[] = { + PROGRESS_BASEBACKUP_BACKUP_STREAMED, + PROGRESS_BASEBACKUP_BACKUP_TOTAL + }; + int64 val[2]; + int nparam = 0; + + backup_streamed += delta; + val[nparam++] = backup_streamed; + + /* + * Avoid overflowing past 100% or the full size. This may make the total + * size number change as we approach the end of the backup (the estimate + * will always be wrong if WAL is included), but that's better than having + * the done column be bigger than the total. + */ + if (backup_total > 0 && backup_streamed > backup_total) + { + backup_total = backup_streamed; + val[nparam++] = backup_total; + } + + pgstat_progress_update_multi_param(nparam, index, val); +} |