Skip to content

Commit 765bba4

Browse files
committed
Merge branch 'issue_146'
2 parents a425a96 + 4e0d1dd commit 765bba4

12 files changed

+323
-359
lines changed

doc/pgprobackup.xml

+34-3
Original file line numberDiff line numberDiff line change
@@ -2402,6 +2402,11 @@ primary_conninfo = 'user=backup passfile=/var/lib/pgsql/.pgpass port=5432 sslmod
24022402
password is not included.
24032403
</para>
24042404
</listitem>
2405+
<listitem>
2406+
<para>
2407+
<literal>note</literal> — text note attached to backup.
2408+
</para>
2409+
</listitem>
24052410
</itemizedlist>
24062411
</para>
24072412
<para>
@@ -3377,15 +3382,28 @@ pg_probackup set-config -B <replaceable>backup_dir</replaceable> --instance <rep
33773382
<title>set-backup</title>
33783383
<programlisting>
33793384
pg_probackup set-backup -B <replaceable>backup_dir</replaceable> --instance <replaceable>instance_name</replaceable> -i <replaceable>backup_id</replaceable>
3380-
{--ttl=<replaceable>ttl</replaceable> | --expire-time=<replaceable>time</replaceable>} [--help]
3385+
{--ttl=<replaceable>ttl</replaceable> | --expire-time=<replaceable>time</replaceable>}
3386+
[--note=<replaceable>backup_note</replaceable>] [--help]
33813387
</programlisting>
33823388
<para>
33833389
Sets the provided backup-specific settings into the
33843390
<filename>backup.control</filename> configuration file, or modifies the previously
33853391
defined values.
33863392
</para>
3393+
<varlistentry>
3394+
<term><option>--note=<replaceable>backup_note</replaceable></option></term>
3395+
<listitem>
33873396
<para>
3388-
For all available settings, see the section
3397+
Sets the text note for backup copy.
3398+
If <replaceable>backup_note</replaceable> contain newline characters,
3399+
then only substring before first newline character will be saved.
3400+
Max size of text note is 1 KB.
3401+
The <replaceable>'none'</replaceable> value removes current note.
3402+
</para>
3403+
</listitem>
3404+
</varlistentry>
3405+
<para>
3406+
For all available pinning settings, see the section
33893407
<link linkend="pbk-pinning-options">Pinning Options</link>.
33903408
</para>
33913409
</refsect3>
@@ -3445,7 +3463,7 @@ pg_probackup backup -B <replaceable>backup_dir</replaceable> -b <replaceable>bac
34453463
[--no-validate] [--skip-block-validation]
34463464
[-w --no-password] [-W --password]
34473465
[--archive-timeout=<replaceable>timeout</replaceable>] [--external-dirs=<replaceable>external_directory_path</replaceable>]
3448-
[--no-sync]
3466+
[--no-sync] [--note=<replaceable>backup_note</replaceable>]
34493467
[<replaceable>connection_options</replaceable>] [<replaceable>compression_options</replaceable>] [<replaceable>remote_options</replaceable>]
34503468
[<replaceable>retention_options</replaceable>] [<replaceable>pinning_options</replaceable>] [<replaceable>logging_options</replaceable>]
34513469
</programlisting>
@@ -3612,6 +3630,19 @@ pg_probackup backup -B <replaceable>backup_dir</replaceable> -b <replaceable>bac
36123630
</para>
36133631
</listitem>
36143632
</varlistentry>
3633+
<varlistentry>
3634+
<term><option>--note=<replaceable>backup_note</replaceable></option></term>
3635+
<listitem>
3636+
<para>
3637+
Sets the text note for backup copy.
3638+
If <replaceable>backup_note</replaceable> contain newline characters,
3639+
then only substring before first newline character will be saved.
3640+
Max size of text note is 1 KB.
3641+
The <replaceable>'none'</replaceable> value removes current note.
3642+
</para>
3643+
</listitem>
3644+
</varlistentry>
3645+
36153646
</variablelist>
36163647
</para>
36173648

src/backup.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync)
156156
/* used for multitimeline incremental backup */
157157
parray *tli_list = NULL;
158158

159-
160159
/* for fancy reporting */
161160
time_t start_time, end_time;
162161
char pretty_time[20];
@@ -820,6 +819,7 @@ do_backup(time_t start_time, bool no_validate,
820819
/* Update backup status and other metainfo. */
821820
current.status = BACKUP_STATUS_RUNNING;
822821
current.start_time = start_time;
822+
823823
StrNCpy(current.program_version, PROGRAM_VERSION,
824824
sizeof(current.program_version));
825825

@@ -902,6 +902,10 @@ do_backup(time_t start_time, bool no_validate,
902902
if (instance_config.master_conn_opt.pghost == NULL)
903903
elog(ERROR, "Options for connection to master must be provided to perform backup from replica");
904904

905+
/* add note to backup if requested */
906+
if (set_backup_params && set_backup_params->note)
907+
add_note(&current, set_backup_params->note);
908+
905909
/* backup data */
906910
do_backup_instance(backup_conn, &nodeInfo, no_sync);
907911
pgut_atexit_pop(backup_cleanup, NULL);
@@ -934,8 +938,7 @@ do_backup(time_t start_time, bool no_validate,
934938
(set_backup_params->ttl > 0 ||
935939
set_backup_params->expire_time > 0))
936940
{
937-
if (!pin_backup(&current, set_backup_params))
938-
elog(ERROR, "Failed to pin the backup %s", base36enc(current.backup_id));
941+
pin_backup(&current, set_backup_params);
939942
}
940943

941944
if (!no_validate)

src/catalog.c

+57-6
Original file line numberDiff line numberDiff line change
@@ -1534,18 +1534,23 @@ do_set_backup(const char *instance_name, time_t backup_id,
15341534

15351535
target_backup = (pgBackup *) parray_get(backup_list, 0);
15361536

1537-
if (!pin_backup(target_backup, set_backup_params))
1538-
elog(ERROR, "Failed to pin the backup %s", base36enc(backup_id));
1537+
/* Pin or unpin backup if requested */
1538+
if (set_backup_params->ttl >= 0 || set_backup_params->expire_time > 0)
1539+
pin_backup(target_backup, set_backup_params);
1540+
1541+
if (set_backup_params->note)
1542+
add_note(target_backup, set_backup_params->note);
15391543
}
15401544

15411545
/*
15421546
* Set 'expire-time' attribute based on set_backup_params, or unpin backup
15431547
* if ttl is equal to zero.
15441548
*/
1545-
bool
1549+
void
15461550
pin_backup(pgBackup *target_backup, pgSetBackupParams *set_backup_params)
15471551
{
15481552

1553+
/* sanity, backup must have positive recovery-time */
15491554
if (target_backup->recovery_time <= 0)
15501555
elog(ERROR, "Failed to set 'expire-time' for backup %s: invalid 'recovery-time'",
15511556
base36enc(target_backup->backup_id));
@@ -1563,15 +1568,16 @@ pin_backup(pgBackup *target_backup, pgSetBackupParams *set_backup_params)
15631568
{
15641569
elog(WARNING, "Backup %s is not pinned, nothing to unpin",
15651570
base36enc(target_backup->start_time));
1566-
return false;
1571+
return;
15671572
}
15681573
target_backup->expire_time = 0;
15691574
}
15701575
/* Pin comes from expire-time */
15711576
else if (set_backup_params->expire_time > 0)
15721577
target_backup->expire_time = set_backup_params->expire_time;
15731578
else
1574-
return false;
1579+
/* nothing to do */
1580+
return;
15751581

15761582
/* Update backup.control */
15771583
write_backup(target_backup);
@@ -1587,7 +1593,44 @@ pin_backup(pgBackup *target_backup, pgSetBackupParams *set_backup_params)
15871593
else
15881594
elog(INFO, "Backup %s is unpinned", base36enc(target_backup->start_time));
15891595

1590-
return true;
1596+
return;
1597+
}
1598+
1599+
/*
1600+
* Add note to backup metadata or unset already existing note.
1601+
* It is a job of the caller to make sure that note is not NULL.
1602+
*/
1603+
void
1604+
add_note(pgBackup *target_backup, char *note)
1605+
{
1606+
1607+
char *note_string;
1608+
1609+
/* unset note */
1610+
if (pg_strcasecmp(note, "none") == 0)
1611+
{
1612+
target_backup->note = NULL;
1613+
elog(INFO, "Removing note from backup %s",
1614+
base36enc(target_backup->start_time));
1615+
}
1616+
else
1617+
{
1618+
/* Currently we do not allow string with newlines as note,
1619+
* because it will break parsing of backup.control.
1620+
* So if user provides string like this "aaa\nbbbbb",
1621+
* we save only "aaa"
1622+
* Example: tests.set_backup.SetBackupTest.test_add_note_newlines
1623+
*/
1624+
note_string = pgut_malloc(MAX_NOTE_SIZE);
1625+
sscanf(note, "%[^\n]", note_string);
1626+
1627+
target_backup->note = note_string;
1628+
elog(INFO, "Adding note to backup %s: '%s'",
1629+
base36enc(target_backup->start_time), target_backup->note);
1630+
}
1631+
1632+
/* Update backup.control */
1633+
write_backup(target_backup);
15911634
}
15921635

15931636
/*
@@ -1682,6 +1725,10 @@ pgBackupWriteControl(FILE *out, pgBackup *backup)
16821725
/* print external directories list */
16831726
if (backup->external_dir_str)
16841727
fio_fprintf(out, "external-dirs = '%s'\n", backup->external_dir_str);
1728+
1729+
if (backup->note)
1730+
fio_fprintf(out, "note = '%s'\n", backup->note);
1731+
16851732
}
16861733

16871734
/*
@@ -1919,6 +1966,7 @@ readBackupControlFile(const char *path)
19191966
{'b', 0, "from-replica", &backup->from_replica, SOURCE_FILE_STRICT},
19201967
{'s', 0, "primary-conninfo", &backup->primary_conninfo, SOURCE_FILE_STRICT},
19211968
{'s', 0, "external-dirs", &backup->external_dir_str, SOURCE_FILE_STRICT},
1969+
{'s', 0, "note", &backup->note, SOURCE_FILE_STRICT},
19221970
{0}
19231971
};
19241972

@@ -2185,6 +2233,8 @@ pgBackupInit(pgBackup *backup)
21852233
backup->external_dir_str = NULL;
21862234
backup->root_dir = NULL;
21872235
backup->files = NULL;
2236+
backup->note = NULL;
2237+
21882238
}
21892239

21902240
/* free pgBackup object */
@@ -2196,6 +2246,7 @@ pgBackupFree(void *backup)
21962246
pfree(b->primary_conninfo);
21972247
pfree(b->external_dir_str);
21982248
pfree(b->root_dir);
2249+
pfree(b->note);
21992250
pfree(backup);
22002251
}
22012252

src/help.c

+13-6
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ help_pg_probackup(void)
106106
printf(_(" [--help]\n"));
107107

108108
printf(_("\n %s set-backup -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
109-
printf(_(" -i backup-id [--ttl] [--expire-time]\n"));
109+
printf(_(" -i backup-id [--ttl=interval] [--expire-time=timestamp]\n"));
110+
printf(_(" [--note=text]\n"));
110111
printf(_(" [--help]\n"));
111112

112113
printf(_("\n %s show-config -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
@@ -140,7 +141,7 @@ help_pg_probackup(void)
140141
printf(_(" [--remote-proto] [--remote-host]\n"));
141142
printf(_(" [--remote-port] [--remote-path] [--remote-user]\n"));
142143
printf(_(" [--ssh-options]\n"));
143-
printf(_(" [--ttl] [--expire-time]\n"));
144+
printf(_(" [--ttl=interval] [--expire-time=timestamp] [--note=text]\n"));
144145
printf(_(" [--help]\n"));
145146

146147

@@ -285,7 +286,7 @@ help_backup(void)
285286
printf(_(" [--remote-proto] [--remote-host]\n"));
286287
printf(_(" [--remote-port] [--remote-path] [--remote-user]\n"));
287288
printf(_(" [--ssh-options]\n"));
288-
printf(_(" [--ttl] [--expire-time]\n\n"));
289+
printf(_(" [--ttl=interval] [--expire-time=timestamp] [--note=text]\n\n"));
289290

290291
printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
291292
printf(_(" -b, --backup-mode=backup-mode backup mode=FULL|PAGE|DELTA|PTRACK\n"));
@@ -304,6 +305,8 @@ help_backup(void)
304305
printf(_(" backup some directories not from pgdata \n"));
305306
printf(_(" (example: --external-dirs=/tmp/dir1:/tmp/dir2)\n"));
306307
printf(_(" --no-sync do not sync backed up files to disk\n"));
308+
printf(_(" --note=text add note to backup\n"));
309+
printf(_(" (example: --note='backup before app update to v13.1')\n"));
307310

308311
printf(_("\n Logging options:\n"));
309312
printf(_(" --log-level-console=log-level-console\n"));
@@ -341,8 +344,9 @@ help_backup(void)
341344
printf(_(" --dry-run perform a trial run without any changes\n"));
342345

343346
printf(_("\n Pinning options:\n"));
344-
printf(_(" --ttl=ttl pin backup for specified amount of time; 0 unpin\n"));
347+
printf(_(" --ttl=interval pin backup for specified amount of time; 0 unpin\n"));
345348
printf(_(" available units: 'ms', 's', 'min', 'h', 'd' (default: s)\n"));
349+
printf(_(" (example: --ttl=20d)\n"));
346350
printf(_(" --expire-time=time pin backup until specified time stamp\n"));
347351
printf(_(" (example: --expire-time='2024-01-01 00:00:00+03')\n"));
348352

@@ -710,12 +714,15 @@ help_set_backup(void)
710714
{
711715
printf(_("\n%s set-backup -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
712716
printf(_(" -i backup-id\n"));
713-
printf(_(" [--ttl] [--expire-time]\n\n"));
717+
printf(_(" [--ttl=interval] [--expire-time=time] [--note=text]\n\n"));
714718

715-
printf(_(" --ttl=ttl pin backup for specified amount of time; 0 unpin\n"));
719+
printf(_(" --ttl=interval pin backup for specified amount of time; 0 unpin\n"));
716720
printf(_(" available units: 'ms', 's', 'min', 'h', 'd' (default: s)\n"));
721+
printf(_(" (example: --ttl=20d)\n"));
717722
printf(_(" --expire-time=time pin backup until specified time stamp\n"));
718723
printf(_(" (example: --expire-time='2024-01-01 00:00:00+03')\n"));
724+
printf(_(" --note=text add note to backup; 'none' to remove note\n"));
725+
printf(_(" (example: --note='backup before app update to v13.1')\n"));
719726
}
720727

721728
static void

src/merge.c

+9
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,15 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup)
702702
full_backup->compress_alg = dest_backup->compress_alg;
703703
full_backup->compress_level = dest_backup->compress_level;
704704

705+
/* If incremental backup is pinned,
706+
* then result FULL backup must also be pinned.
707+
*/
708+
if (dest_backup->expire_time)
709+
full_backup->expire_time = dest_backup->expire_time;
710+
711+
if (dest_backup->note)
712+
full_backup->note = pgut_strdup(dest_backup->note);
713+
705714
/* FULL backup must inherit wal mode. */
706715
full_backup->stream = dest_backup->stream;
707716

src/pg_probackup.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ char *replication_slot = NULL;
7575
bool temp_slot = false;
7676

7777
/* backup options */
78-
bool backup_logs = false;
79-
bool smooth_checkpoint;
80-
char *remote_agent;
81-
78+
bool backup_logs = false;
79+
bool smooth_checkpoint;
80+
char *remote_agent;
81+
static char *backup_note = NULL;
8282
/* restore options */
8383
static char *target_time = NULL;
8484
static char *target_xid = NULL;
@@ -183,6 +183,7 @@ static ConfigOption cmd_options[] =
183183
{ 'b', 183, "delete-expired", &delete_expired, SOURCE_CMD_STRICT },
184184
{ 'b', 184, "merge-expired", &merge_expired, SOURCE_CMD_STRICT },
185185
{ 'b', 185, "dry-run", &dry_run, SOURCE_CMD_STRICT },
186+
{ 's', 238, "note", &backup_note, SOURCE_CMD_STRICT },
186187
/* restore options */
187188
{ 's', 136, "recovery-target-time", &target_time, SOURCE_CMD_STRICT },
188189
{ 's', 137, "recovery-target-xid", &target_xid, SOURCE_CMD_STRICT },
@@ -746,11 +747,15 @@ main(int argc, char *argv[])
746747
expire_time_string);
747748
}
748749

749-
if (expire_time > 0 || ttl >= 0)
750+
if (expire_time > 0 || ttl >= 0 || backup_note)
750751
{
751752
set_backup_params = pgut_new(pgSetBackupParams);
752753
set_backup_params->ttl = ttl;
753754
set_backup_params->expire_time = expire_time;
755+
set_backup_params->note = backup_note;
756+
757+
if (backup_note && strlen(backup_note) > MAX_NOTE_SIZE)
758+
elog(ERROR, "Backup note cannot exceed %u bytes", MAX_NOTE_SIZE);
754759
}
755760
}
756761

0 commit comments

Comments
 (0)