mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
WIP support for preserving failover slots
This commit is contained in:
committed by
Ian Barwick
parent
925d82f7a4
commit
c22f4eaf6f
@@ -37,5 +37,6 @@
|
||||
#define ERR_BAD_BASEBACKUP 14
|
||||
#define ERR_INTERNAL 15
|
||||
#define ERR_MONITORING_FAIL 16
|
||||
#define ERR_BAD_BACKUP_LABEL 17
|
||||
|
||||
#endif /* _ERRCODE_H_ */
|
||||
|
||||
159
repmgr.c
159
repmgr.c
@@ -121,6 +121,8 @@ static bool remote_command(const char *host, const char *user, const char *comma
|
||||
static void format_db_cli_params(const char *conninfo, char *output);
|
||||
static bool copy_file(const char *old_filename, const char *new_filename);
|
||||
|
||||
static void read_backup_label(const char *local_data_directory, struct BackupLabel *backup_label);
|
||||
|
||||
/* Global variables */
|
||||
static const char *keywords[6];
|
||||
static const char *values[6];
|
||||
@@ -142,6 +144,8 @@ static char repmgr_slot_name[MAXLEN] = "";
|
||||
static char *repmgr_slot_name_ptr = NULL;
|
||||
static char path_buf[MAXLEN] = "";
|
||||
|
||||
static struct BackupLabel backup_label;
|
||||
|
||||
/* Collate command line errors and warnings here for friendlier reporting */
|
||||
ErrorList cli_errors = { NULL, NULL };
|
||||
ErrorList cli_warnings = { NULL, NULL };
|
||||
@@ -1971,6 +1975,8 @@ stop_backup:
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
read_backup_label(local_data_directory, &backup_label);
|
||||
|
||||
/*
|
||||
* Clean up any $PGDATA subdirectories which may contain
|
||||
* files which won't be removed by rsync and which could
|
||||
@@ -1999,12 +2005,17 @@ stop_backup:
|
||||
* behaviour a base backup, which would result in an empty
|
||||
* pg_replslot directory.
|
||||
*
|
||||
* If the backup label contains a nonzero
|
||||
* 'MIN FAILOVER SLOT LSN' entry we retain the slots and let
|
||||
* the server clean them up instead, matching pg_basebackup's
|
||||
* behaviour when failover slots are enabled.
|
||||
*
|
||||
* NOTE: watch out for any changes in the replication
|
||||
* slot directory name (as of 9.4: "pg_replslot") and
|
||||
* functionality of replication slots
|
||||
*/
|
||||
|
||||
if (server_version_num >= 90400)
|
||||
if (server_version_num >= 90400 &&
|
||||
backup_label.min_failover_slot_lsn == InvalidXLogRecPtr)
|
||||
{
|
||||
maxlen_snprintf(script, "rm -rf %s/pg_replslot/*",
|
||||
local_data_directory);
|
||||
@@ -2100,6 +2111,150 @@ stop_backup:
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_lsn(XLogRecPtr *ptr, const char *str)
|
||||
{
|
||||
uint32 high, low;
|
||||
|
||||
if (sscanf(str, "%x/%x", &high, &low) != 2)
|
||||
return false;
|
||||
|
||||
*ptr = (((XLogRecPtr)high) << 32) + (XLogRecPtr)low;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static XLogRecPtr
|
||||
parse_label_lsn(const char *label_key, const char *label_value)
|
||||
{
|
||||
XLogRecPtr ptr;
|
||||
|
||||
if (!parse_lsn(&ptr, label_value))
|
||||
{
|
||||
log_err(_("Couldn't parse backup label entry \"%s: %s\" as lsn"),
|
||||
label_key, label_value);
|
||||
|
||||
exit(ERR_BAD_BACKUP_LABEL);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*======================================
|
||||
* Read entries of interest from the backup label.
|
||||
*
|
||||
* Sample backup label:
|
||||
*
|
||||
* START WAL LOCATION: 0/6000028 (file 000000010000000000000006)
|
||||
* CHECKPOINT LOCATION: 0/6000060
|
||||
* BACKUP METHOD: streamed
|
||||
* BACKUP FROM: master
|
||||
* START TIME: 2016-03-30 12:18:12 AWST
|
||||
* LABEL: pg_basebackup base backup
|
||||
* MIN FAILOVER SLOT LSN: 0/5000000
|
||||
*
|
||||
*======================================
|
||||
*/
|
||||
static void
|
||||
read_backup_label(const char *local_data_directory, struct BackupLabel *out_backup_label)
|
||||
{
|
||||
char label_path[MAXFILENAME];
|
||||
FILE *label_file;
|
||||
int nmatches = 0;
|
||||
char label_key[MAXLEN];
|
||||
char label_value[MAXLEN];
|
||||
|
||||
out_backup_label->start_wal_location = InvalidXLogRecPtr;
|
||||
out_backup_label->checkpoint_location = InvalidXLogRecPtr;
|
||||
out_backup_label->backup_from[0] = '\0';
|
||||
out_backup_label->backup_method[0] = '\0';
|
||||
out_backup_label->start_time[0] = '\0';
|
||||
out_backup_label->label[0] = '\0';
|
||||
out_backup_label->min_failover_slot_lsn = InvalidXLogRecPtr;
|
||||
|
||||
maxlen_snprintf(label_path, "%s/backup_label", local_data_directory);
|
||||
|
||||
label_file = fopen(label_path, "r");
|
||||
if (label_file == NULL)
|
||||
{
|
||||
log_err(_("could not open backup label file %s: %s"),
|
||||
label_path, strerror(errno));
|
||||
exit(ERR_BAD_BACKUP_LABEL);
|
||||
}
|
||||
|
||||
log_info(_("standby clone: backup label file '%s'\n"),
|
||||
label_path);
|
||||
|
||||
do
|
||||
{
|
||||
char newline;
|
||||
|
||||
/*
|
||||
* Scan a line, including newline char.
|
||||
*
|
||||
* See http://stackoverflow.com/a/8097776/398670
|
||||
*/
|
||||
nmatches = fscanf(label_file, "%" MAXLEN_STR "s: %" MAXLEN_STR "[^\n]%c",
|
||||
&label_key[0], &label_value[0], &newline);
|
||||
|
||||
if (nmatches != 3)
|
||||
break;
|
||||
|
||||
if (newline != '\n')
|
||||
{
|
||||
log_err(_("standby clone: line too long in backup label file. Line begins \"%s: %s\""),
|
||||
label_key, label_value);
|
||||
exit(ERR_BAD_BACKUP_LABEL);
|
||||
}
|
||||
|
||||
log_debug("standby clone: got backup label entry \"%s: %s\"",
|
||||
label_key, label_value);
|
||||
|
||||
if (strcmp(label_key, "START WAL LOCATION") == 0)
|
||||
{
|
||||
out_backup_label->start_wal_location =
|
||||
parse_label_lsn(&label_key[0], &label_value[0]);
|
||||
}
|
||||
else if (strcmp(label_key, "CHECKPOINT LOCATION") == 0)
|
||||
{
|
||||
out_backup_label->checkpoint_location =
|
||||
parse_label_lsn(&label_key[0], &label_value[0]);
|
||||
}
|
||||
else if (strcmp(label_key, "BACKUP METHOD") == 0)
|
||||
{
|
||||
(void) strncpy(out_backup_label->backup_method, label_value, MAXLEN);
|
||||
out_backup_label->backup_method[MAXLEN-1] = '\0';
|
||||
}
|
||||
else if (strcmp(label_key, "BACKUP FROM") == 0)
|
||||
{
|
||||
(void) strncpy(out_backup_label->backup_from, label_value, MAXLEN);
|
||||
out_backup_label->backup_from[MAXLEN-1] = '\0';
|
||||
}
|
||||
else if (strcmp(label_key, "START TIME") == 0)
|
||||
{
|
||||
(void) strncpy(out_backup_label->start_time, label_value, MAXLEN);
|
||||
out_backup_label->start_time[MAXLEN-1] = '\0';
|
||||
}
|
||||
else if (strcmp(label_key, "LABEL") == 0)
|
||||
{
|
||||
(void) strncpy(out_backup_label->label, label_value, MAXLEN);
|
||||
out_backup_label->label[MAXLEN-1] = '\0';
|
||||
}
|
||||
else if (strcmp(label_key, "MIN FAILOVER SLOT LSN") == 0)
|
||||
{
|
||||
out_backup_label->min_failover_slot_lsn =
|
||||
parse_label_lsn(&label_key[0], &label_value[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("standby clone: ignored unrecognised backup label entry \"%s: %s\"",
|
||||
label_key, label_value);
|
||||
}
|
||||
}
|
||||
while (!feof(label_file));
|
||||
|
||||
(void) fclose(label_file);
|
||||
}
|
||||
|
||||
static void
|
||||
do_standby_promote(void)
|
||||
|
||||
11
repmgr.h
11
repmgr.h
@@ -97,6 +97,17 @@ typedef struct
|
||||
|
||||
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, "smart", "", "", "", "", "", 0, "", "", "", false }
|
||||
|
||||
struct BackupLabel
|
||||
{
|
||||
XLogRecPtr start_wal_location;
|
||||
XLogRecPtr checkpoint_location;
|
||||
char backup_from[MAXLEN];
|
||||
char backup_method[MAXLEN];
|
||||
char start_time[MAXLEN];
|
||||
char label[MAXLEN];
|
||||
XLogRecPtr min_failover_slot_lsn;
|
||||
};
|
||||
|
||||
extern char repmgr_schema[MAXLEN];
|
||||
extern bool config_file_found;
|
||||
|
||||
|
||||
@@ -24,12 +24,17 @@
|
||||
#include <stdlib.h>
|
||||
#include "errcode.h"
|
||||
|
||||
|
||||
#define QUERY_STR_LEN 8192
|
||||
#define MAXLEN 1024
|
||||
#define MAXLINELENGTH 4096
|
||||
#define MAXVERSIONSTR 16
|
||||
#define MAXCONNINFO 1024
|
||||
|
||||
/* Why? http://stackoverflow.com/a/5459929/398670 */
|
||||
#define STR(x) CppAsString(x)
|
||||
|
||||
#define MAXLEN_STR STR(MAXLEN)
|
||||
|
||||
extern int
|
||||
xsnprintf(char *str, size_t size, const char *format,...)
|
||||
|
||||
Reference in New Issue
Block a user