LCOV - code coverage report
Current view: top level - src/backend/backup - basebackup_progress.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 98.1 % 54 53
Test Date: 2026-03-03 02:14:47 Functions: 100.0 % 9 9
Legend: Lines:     hit not hit

            Line data    Source code
       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-2026, 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_sink.h"
      35              : #include "commands/progress.h"
      36              : #include "pgstat.h"
      37              : 
      38              : static void bbsink_progress_begin_backup(bbsink *sink);
      39              : static void bbsink_progress_archive_contents(bbsink *sink, size_t len);
      40              : static void bbsink_progress_end_archive(bbsink *sink);
      41              : 
      42              : static const bbsink_ops bbsink_progress_ops = {
      43              :     .begin_backup = bbsink_progress_begin_backup,
      44              :     .begin_archive = bbsink_forward_begin_archive,
      45              :     .archive_contents = bbsink_progress_archive_contents,
      46              :     .end_archive = bbsink_progress_end_archive,
      47              :     .begin_manifest = bbsink_forward_begin_manifest,
      48              :     .manifest_contents = bbsink_forward_manifest_contents,
      49              :     .end_manifest = bbsink_forward_end_manifest,
      50              :     .end_backup = bbsink_forward_end_backup,
      51              :     .cleanup = bbsink_forward_cleanup
      52              : };
      53              : 
      54              : /*
      55              :  * Create a new basebackup sink that performs progress tracking functions and
      56              :  * forwards data to a successor sink.
      57              :  */
      58              : bbsink *
      59          169 : bbsink_progress_new(bbsink *next, bool estimate_backup_size, bool incremental)
      60              : {
      61              :     bbsink     *sink;
      62              : 
      63              :     Assert(next != NULL);
      64              : 
      65          169 :     sink = palloc0_object(bbsink);
      66          169 :     *((const bbsink_ops **) &sink->bbs_ops) = &bbsink_progress_ops;
      67          169 :     sink->bbs_next = next;
      68              : 
      69              :     /*
      70              :      * Report that a base backup is in progress, and set the total size of the
      71              :      * backup to -1, which will get translated to NULL. If we're estimating
      72              :      * the backup size, we'll insert the real estimate when we have it. Also,
      73              :      * the backup type is set.
      74              :      */
      75          169 :     pgstat_progress_start_command(PROGRESS_COMMAND_BASEBACKUP, InvalidOid);
      76          169 :     pgstat_progress_update_param(PROGRESS_BASEBACKUP_BACKUP_TOTAL, -1);
      77          169 :     pgstat_progress_update_param(PROGRESS_BASEBACKUP_BACKUP_TYPE,
      78              :                                  incremental
      79              :                                  ? PROGRESS_BASEBACKUP_BACKUP_TYPE_INCREMENTAL
      80              :                                  : PROGRESS_BASEBACKUP_BACKUP_TYPE_FULL);
      81              : 
      82          169 :     return sink;
      83              : }
      84              : 
      85              : /*
      86              :  * Progress reporting at start of backup.
      87              :  */
      88              : static void
      89          169 : bbsink_progress_begin_backup(bbsink *sink)
      90              : {
      91          169 :     const int   index[] = {
      92              :         PROGRESS_BASEBACKUP_PHASE,
      93              :         PROGRESS_BASEBACKUP_BACKUP_TOTAL,
      94              :         PROGRESS_BASEBACKUP_TBLSPC_TOTAL
      95              :     };
      96              :     int64       val[3];
      97              : 
      98              :     /*
      99              :      * Report that we are now streaming database files as a base backup. Also
     100              :      * advertise the number of tablespaces, and, if known, the estimated total
     101              :      * backup size.
     102              :      */
     103          169 :     val[0] = PROGRESS_BASEBACKUP_PHASE_STREAM_BACKUP;
     104          169 :     if (sink->bbs_state->bytes_total_is_valid)
     105          169 :         val[1] = sink->bbs_state->bytes_total;
     106              :     else
     107            0 :         val[1] = -1;
     108          169 :     val[2] = list_length(sink->bbs_state->tablespaces);
     109          169 :     pgstat_progress_update_multi_param(3, index, val);
     110              : 
     111              :     /* Delegate to next sink. */
     112          169 :     bbsink_forward_begin_backup(sink);
     113          169 : }
     114              : 
     115              : /*
     116              :  * End-of archive progress reporting.
     117              :  */
     118              : static void
     119          201 : bbsink_progress_end_archive(bbsink *sink)
     120              : {
     121              :     /*
     122              :      * We expect one archive per tablespace, so reaching the end of an archive
     123              :      * also means reaching the end of a tablespace. (Some day we might have a
     124              :      * reason to decouple these concepts.)
     125              :      *
     126              :      * If WAL is included in the backup, we'll mark the last tablespace
     127              :      * complete before the last archive is complete, so we need a guard here
     128              :      * to ensure that the number of tablespaces streamed doesn't exceed the
     129              :      * total.
     130              :      */
     131          201 :     if (sink->bbs_state->tablespace_num < list_length(sink->bbs_state->tablespaces))
     132          201 :         pgstat_progress_update_param(PROGRESS_BASEBACKUP_TBLSPC_STREAMED,
     133          201 :                                      sink->bbs_state->tablespace_num + 1);
     134              : 
     135              :     /* Delegate to next sink. */
     136          201 :     bbsink_forward_end_archive(sink);
     137              : 
     138              :     /*
     139              :      * This is a convenient place to update the bbsink_state's notion of which
     140              :      * is the current tablespace. Note that the bbsink_state object is shared
     141              :      * across all bbsink objects involved, but we're the outermost one and
     142              :      * this is the very last thing we do.
     143              :      */
     144          201 :     sink->bbs_state->tablespace_num++;
     145          201 : }
     146              : 
     147              : /*
     148              :  * Handle progress tracking for new archive contents.
     149              :  *
     150              :  * Increment the counter for the amount of data already streamed
     151              :  * by the given number of bytes, and update the progress report for
     152              :  * pg_stat_progress_basebackup.
     153              :  */
     154              : static void
     155       383504 : bbsink_progress_archive_contents(bbsink *sink, size_t len)
     156              : {
     157       383504 :     bbsink_state *state = sink->bbs_state;
     158       383504 :     const int   index[] = {
     159              :         PROGRESS_BASEBACKUP_BACKUP_STREAMED,
     160              :         PROGRESS_BASEBACKUP_BACKUP_TOTAL
     161              :     };
     162              :     int64       val[2];
     163       383504 :     int         nparam = 0;
     164              : 
     165              :     /* First update bbsink_state with # of bytes done. */
     166       383504 :     state->bytes_done += len;
     167              : 
     168              :     /* Now forward to next sink. */
     169       383504 :     bbsink_forward_archive_contents(sink, len);
     170              : 
     171              :     /* Prepare to set # of bytes done for command progress reporting. */
     172       383504 :     val[nparam++] = state->bytes_done;
     173              : 
     174              :     /*
     175              :      * We may also want to update # of total bytes, to avoid overflowing past
     176              :      * 100% or the full size. This may make the total size number change as we
     177              :      * approach the end of the backup (the estimate will always be wrong if
     178              :      * WAL is included), but that's better than having the done column be
     179              :      * bigger than the total.
     180              :      */
     181       383504 :     if (state->bytes_total_is_valid && state->bytes_done > state->bytes_total)
     182         8624 :         val[nparam++] = state->bytes_done;
     183              : 
     184       383504 :     pgstat_progress_update_multi_param(nparam, index, val);
     185       383504 : }
     186              : 
     187              : /*
     188              :  * Advertise that we are waiting for the start-of-backup checkpoint.
     189              :  */
     190              : void
     191          169 : basebackup_progress_wait_checkpoint(void)
     192              : {
     193          169 :     pgstat_progress_update_param(PROGRESS_BASEBACKUP_PHASE,
     194              :                                  PROGRESS_BASEBACKUP_PHASE_WAIT_CHECKPOINT);
     195          169 : }
     196              : 
     197              : /*
     198              :  * Advertise that we are estimating the backup size.
     199              :  */
     200              : void
     201          169 : basebackup_progress_estimate_backup_size(void)
     202              : {
     203          169 :     pgstat_progress_update_param(PROGRESS_BASEBACKUP_PHASE,
     204              :                                  PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE);
     205          169 : }
     206              : 
     207              : /*
     208              :  * Advertise that we are waiting for WAL archiving at end-of-backup.
     209              :  */
     210              : void
     211          164 : basebackup_progress_wait_wal_archive(bbsink_state *state)
     212              : {
     213          164 :     const int   index[] = {
     214              :         PROGRESS_BASEBACKUP_PHASE,
     215              :         PROGRESS_BASEBACKUP_TBLSPC_STREAMED
     216              :     };
     217              :     int64       val[2];
     218              : 
     219              :     /*
     220              :      * We report having finished all tablespaces at this point, even if the
     221              :      * archive for the main tablespace is still open, because what's going to
     222              :      * be added is WAL files, not files that are really from the main
     223              :      * tablespace.
     224              :      */
     225          164 :     val[0] = PROGRESS_BASEBACKUP_PHASE_WAIT_WAL_ARCHIVE;
     226          164 :     val[1] = list_length(state->tablespaces);
     227          164 :     pgstat_progress_update_multi_param(2, index, val);
     228          164 : }
     229              : 
     230              : /*
     231              :  * Advertise that we are transferring WAL files into the final archive.
     232              :  */
     233              : void
     234           15 : basebackup_progress_transfer_wal(void)
     235              : {
     236           15 :     pgstat_progress_update_param(PROGRESS_BASEBACKUP_PHASE,
     237              :                                  PROGRESS_BASEBACKUP_PHASE_TRANSFER_WAL);
     238           15 : }
     239              : 
     240              : /*
     241              :  * Advertise that we are no longer performing a backup.
     242              :  */
     243              : void
     244          161 : basebackup_progress_done(void)
     245              : {
     246          161 :     pgstat_progress_end_command();
     247          161 : }
        

Generated by: LCOV version 2.0-1