1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-28 09:33:54 +02:00

PGPRO-2071: Refactor pg_probackup configure set/get, use InstanceConfig

This commit is contained in:
Arthur Zakirov 2018-11-01 19:10:20 +03:00
parent 141ba33000
commit 77c59158be
29 changed files with 2295 additions and 2215 deletions

View File

@ -1,8 +1,8 @@
PROGRAM = pg_probackup
# utils
OBJS = src/utils/json.o src/utils/logger.o src/utils/parray.o \
src/utils/pgut.o src/utils/thread.o
OBJS = src/utils/configuration.o src/utils/json.o src/utils/logger.o \
src/utils/parray.o src/utils/pgut.o src/utils/thread.o
OBJS += src/archive.o src/backup.o src/catalog.o src/configure.o src/data.o \
src/delete.o src/dir.o src/fetch.o src/help.o src/init.o src/merge.o \

View File

@ -149,7 +149,8 @@ sub build_pgprobackup
'validate.c'
);
$probackup->AddFiles(
'contrib/pg_probackup/src/utils',
'contrib/pg_probackup/src/utils',
'configuration.c',
'json.c',
'logger.c',
'parray.c',

View File

@ -187,6 +187,7 @@
<ClCompile Include="..\src\show.c" />
<ClCompile Include="..\src\status.c" />
<ClCompile Include="..\src\util.c" />
<ClCompile Include="..\src\utils\configuration.c" />
<ClCompile Include="..\src\utils\logger.c" />
<ClCompile Include="..\src\utils\parray.c" />
<ClCompile Include="..\src\utils\pgut.c" />
@ -201,6 +202,7 @@
<ClInclude Include="@PGSRC@\bin\pg_rewind\datapagemap.h" />
<ClInclude Include="@PGSRC@\bin\pg_rewind\logging.h" />
<ClInclude Include="..\src\pg_probackup.h" />
<ClInclude Include="..\src\utils\configuration.h" />
<ClInclude Include="..\src\utils\logger.h" />
<ClInclude Include="..\src\utils\parray.h" />
<ClInclude Include="..\src\utils\pgut.h" />

View File

@ -186,6 +186,7 @@
<ClCompile Include="..\src\show.c" />
<ClCompile Include="..\src\status.c" />
<ClCompile Include="..\src\util.c" />
<ClCompile Include="..\src\utils\configuration.c" />
<ClCompile Include="..\src\utils\logger.c" />
<ClCompile Include="..\src\utils\parray.c" />
<ClCompile Include="..\src\utils\pgut.c" />
@ -199,6 +200,7 @@
<ClInclude Include="@PGSRC@\bin\pg_rewind\datapagemap.h" />
<ClInclude Include="@PGSRC@\bin\pg_rewind\logging.h" />
<ClInclude Include="..\src\pg_probackup.h" />
<ClInclude Include="..\src\utils\configuration.h" />
<ClInclude Include="..\src\utils\logger.h" />
<ClInclude Include="..\src\utils\parray.h" />
<ClInclude Include="..\src\utils\pgut.h" />

View File

@ -182,6 +182,7 @@
<ClCompile Include="..\src\show.c" />
<ClCompile Include="..\src\status.c" />
<ClCompile Include="..\src\util.c" />
<ClCompile Include="..\src\utils\configuration.c" />
<ClCompile Include="..\src\utils\logger.c" />
<ClCompile Include="..\src\utils\parray.c" />
<ClCompile Include="..\src\utils\pgut.c" />
@ -194,6 +195,7 @@
<ClInclude Include="@PGSRC@\bin\pg_rewind\datapagemap.h" />
<ClInclude Include="@PGSRC@\bin\pg_rewind\logging.h" />
<ClInclude Include="..\src\pg_probackup.h" />
<ClInclude Include="..\src\utils\configuration.h" />
<ClInclude Include="..\src\utils\logger.h" />
<ClInclude Include="..\src\utils\parray.h" />
<ClInclude Include="..\src\utils\pgut.h" />

View File

@ -28,7 +28,6 @@ do_archive_push(char *wal_file_path, char *wal_file_name, bool overwrite)
char absolute_wal_file_path[MAXPGPATH];
char current_dir[MAXPGPATH];
int64 system_id;
pgBackupConfig *config;
bool is_compress = false;
if (wal_file_name == NULL && wal_file_path == NULL)
@ -44,16 +43,16 @@ do_archive_push(char *wal_file_path, char *wal_file_name, bool overwrite)
elog(ERROR, "getcwd() error");
/* verify that archive-push --instance parameter is valid */
config = readBackupCatalogConfigFile();
system_id = get_system_identifier(current_dir);
if (config->pgdata == NULL)
if (instance_config.pgdata == NULL)
elog(ERROR, "cannot read pg_probackup.conf for this instance");
if(system_id != config->system_identifier)
if(system_id != instance_config.system_identifier)
elog(ERROR, "Refuse to push WAL segment %s into archive. Instance parameters mismatch."
"Instance '%s' should have SYSTEM_ID = %ld instead of %ld",
wal_file_name, instance_name, config->system_identifier, system_id);
wal_file_name, instance_name, instance_config.system_identifier,
system_id);
/* Create 'archlog_path' directory. Do nothing if it already exists. */
dir_create_dir(arclog_path, DIR_PERMISSION);
@ -63,11 +62,11 @@ do_archive_push(char *wal_file_path, char *wal_file_name, bool overwrite)
elog(INFO, "pg_probackup archive-push from %s to %s", absolute_wal_file_path, backup_wal_file_path);
if (compress_alg == PGLZ_COMPRESS)
if (instance_config.compress_alg == PGLZ_COMPRESS)
elog(ERROR, "pglz compression is not supported");
#ifdef HAVE_LIBZ
if (compress_alg == ZLIB_COMPRESS)
if (instance_config.compress_alg == ZLIB_COMPRESS)
is_compress = IsXLogFileName(wal_file_name);
#endif

View File

@ -150,7 +150,10 @@ get_remote_pgdata_filelist(parray *files)
int resultStatus;
int i;
backup_conn_replication = pgut_connect_replication(pgut_dbname);
backup_conn_replication = pgut_connect_replication(instance_config.pghost,
instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
if (PQsendQuery(backup_conn_replication, "FILE_BACKUP FILELIST") == 0)
elog(ERROR,"%s: could not send replication command \"%s\": %s",
@ -397,7 +400,10 @@ remote_backup_files(void *arg)
if (!pg_atomic_test_set_flag(&file->lock))
continue;
file_backup_conn = pgut_connect_replication(pgut_dbname);
file_backup_conn = pgut_connect_replication(instance_config.pghost,
instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
/* check for interrupt */
if (interrupted)
@ -487,16 +493,19 @@ do_backup_instance(void)
TimeLineID starttli;
XLogRecPtr startpos;
backup_conn_replication = pgut_connect_replication(pgut_dbname);
backup_conn_replication = pgut_connect_replication(instance_config.pghost,
instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
/* Check replication prorocol connection */
if (!RunIdentifySystem(backup_conn_replication, &sysidentifier, &starttli, &startpos, NULL))
elog(ERROR, "Failed to send command for remote backup");
// TODO implement the check
// if (&sysidentifier != system_identifier)
// if (&sysidentifier != instance_config.system_identifier)
// elog(ERROR, "Backup data directory was initialized for system id %ld, but target backup directory system id is %ld",
// system_identifier, sysidentifier);
// instance_config.system_identifier, sysidentifier);
current.tli = starttli;
@ -579,7 +588,10 @@ do_backup_instance(void)
/*
* Connect in replication mode to the server.
*/
stream_thread_arg.conn = pgut_connect_replication(pgut_dbname);
stream_thread_arg.conn = pgut_connect_replication(instance_config.pghost,
instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
if (!CheckServerVersionForStreaming(stream_thread_arg.conn))
{
@ -616,7 +628,8 @@ do_backup_instance(void)
if (is_remote_backup)
get_remote_pgdata_filelist(backup_files_list);
else
dir_list_file(backup_files_list, pgdata, true, true, false);
dir_list_file(backup_files_list, instance_config.pgdata,
true, true, false);
/*
* Sort pathname ascending. It is necessary to create intermediate
@ -632,7 +645,7 @@ do_backup_instance(void)
parray_qsort(backup_files_list, pgFileComparePath);
/* Extract information about files in backup_list parsing their names:*/
parse_backup_filelist_filenames(backup_files_list, pgdata);
parse_backup_filelist_filenames(backup_files_list, instance_config.pgdata);
if (current.backup_mode != BACKUP_MODE_FULL)
{
@ -653,7 +666,7 @@ do_backup_instance(void)
* reading WAL segments present in archives up to the point
* where this backup has started.
*/
extractPageMap(arclog_path, current.tli, xlog_seg_size,
extractPageMap(arclog_path, current.tli, instance_config.xlog_seg_size,
prev_backup->start_lsn, current.start_lsn,
backup_files_list);
}
@ -680,7 +693,7 @@ do_backup_instance(void)
char database_path[MAXPGPATH];
if (!is_remote_backup)
dir_name = GetRelativePath(file->path, pgdata);
dir_name = GetRelativePath(file->path, instance_config.pgdata);
else
dir_name = file->path;
@ -710,7 +723,7 @@ do_backup_instance(void)
{
backup_files_arg *arg = &(threads_args[i]);
arg->from_root = pgdata;
arg->from_root = instance_config.pgdata;
arg->to_root = database_path;
arg->files_list = backup_files_list;
arg->prev_filelist = prev_backup_filelist;
@ -790,7 +803,7 @@ do_backup_instance(void)
}
/* Print the list of files to backup catalog */
pgBackupWriteFileList(&current, backup_files_list, pgdata);
pgBackupWriteFileList(&current, backup_files_list, instance_config.pgdata);
/* Compute summary of size of regular files in the backup */
for (i = 0; i < parray_num(backup_files_list); i++)
@ -816,9 +829,8 @@ do_backup_instance(void)
int
do_backup(time_t start_time)
{
/* PGDATA and BACKUP_MODE are always required */
if (pgdata == NULL)
if (instance_config.pgdata == NULL)
elog(ERROR, "required parameter not specified: PGDATA "
"(-D, --pgdata)");
if (current.backup_mode == BACKUP_MODE_INVALID)
@ -826,7 +838,9 @@ do_backup(time_t start_time)
"(-b, --backup-mode)");
/* Create connection for PostgreSQL */
backup_conn = pgut_connect(pgut_dbname);
backup_conn = pgut_connect(instance_config.pghost, instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
pgut_atexit_push(backup_disconnect, NULL);
current.primary_conninfo = pgut_get_conninfo_string(backup_conn);
@ -836,8 +850,8 @@ do_backup(time_t start_time)
elog(ERROR, "Failed to retreive wal_segment_size");
#endif
current.compress_alg = compress_alg;
current.compress_level = compress_level;
current.compress_alg = instance_config.compress_alg;
current.compress_level = instance_config.compress_level;
/* Confirm data block size and xlog block size are compatible */
confirm_block_size("block_size", BLCKSZ);
@ -886,11 +900,14 @@ do_backup(time_t start_time)
if (current.from_replica)
{
/* Check master connection options */
if (master_host == NULL)
if (instance_config.master_host == NULL)
elog(ERROR, "Options for connection to master must be provided to perform backup from replica");
/* Create connection to master server */
master_conn = pgut_connect_extended(master_host, master_port, master_db, master_user);
master_conn = pgut_connect(instance_config.master_host,
instance_config.master_port,
instance_config.master_db,
instance_config.master_user);
}
/* Get exclusive lock of backup catalog */
@ -929,9 +946,9 @@ do_backup(time_t start_time)
/* compute size of wal files of this backup stored in the archive */
if (!current.stream)
{
current.wal_bytes = xlog_seg_size *
(current.stop_lsn / xlog_seg_size -
current.start_lsn / xlog_seg_size + 1);
current.wal_bytes = instance_config.xlog_seg_size *
(current.stop_lsn / instance_config.xlog_seg_size -
current.start_lsn / instance_config.xlog_seg_size + 1);
}
/* Backup is done. Update backup status */
@ -1038,17 +1055,17 @@ check_system_identifiers(void)
uint64 system_id_conn;
uint64 system_id_pgdata;
system_id_pgdata = get_system_identifier(pgdata);
system_id_pgdata = get_system_identifier(instance_config.pgdata);
system_id_conn = get_remote_system_identifier(backup_conn);
if (system_id_conn != system_identifier)
if (system_id_conn != instance_config.system_identifier)
elog(ERROR, "Backup data directory was initialized for system id " UINT64_FORMAT ", "
"but connected instance system id is " UINT64_FORMAT,
system_identifier, system_id_conn);
if (system_id_pgdata != system_identifier)
instance_config.system_identifier, system_id_conn);
if (system_id_pgdata != instance_config.system_identifier)
elog(ERROR, "Backup data directory was initialized for system id " UINT64_FORMAT ", "
"but target backup directory system id is " UINT64_FORMAT,
system_identifier, system_id_pgdata);
instance_config.system_identifier, system_id_pgdata);
}
/*
@ -1283,7 +1300,9 @@ pg_ptrack_clear(void)
dbOid = atoi(PQgetvalue(res_db, i, 1));
tblspcOid = atoi(PQgetvalue(res_db, i, 2));
tmp_conn = pgut_connect(dbname);
tmp_conn = pgut_connect(instance_config.pghost, instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
res = pgut_execute(tmp_conn, "SELECT pg_catalog.pg_ptrack_clear()",
0, NULL);
PQclear(res);
@ -1399,7 +1418,9 @@ pg_ptrack_get_and_clear(Oid tablespace_oid, Oid db_oid, Oid rel_filenode,
return NULL;
}
tmp_conn = pgut_connect(dbname);
tmp_conn = pgut_connect(instance_config.pghost, instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
sprintf(params[0], "%i", tablespace_oid);
sprintf(params[1], "%i", rel_filenode);
res = pgut_execute(tmp_conn, "SELECT pg_catalog.pg_ptrack_get_and_clear($1, $2)",
@ -1482,10 +1503,11 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
tli = get_current_timeline(false);
/* Compute the name of the WAL file containig requested LSN */
GetXLogSegNo(lsn, targetSegNo, xlog_seg_size);
GetXLogSegNo(lsn, targetSegNo, instance_config.xlog_seg_size);
if (wait_prev_segment)
targetSegNo--;
GetXLogFileName(wal_segment, tli, targetSegNo, xlog_seg_size);
GetXLogFileName(wal_segment, tli, targetSegNo,
instance_config.xlog_seg_size);
/*
* In pg_start_backup we wait for 'lsn' in 'pg_wal' directory iff it is
@ -1509,7 +1531,7 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
{
join_path_components(wal_segment_path, arclog_path, wal_segment);
wal_segment_dir = arclog_path;
timeout = archive_timeout;
timeout = instance_config.archive_timeout;
}
if (wait_prev_segment)
@ -1552,7 +1574,8 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
/*
* A WAL segment found. Check LSN on it.
*/
if (wal_contains_lsn(wal_segment_dir, lsn, tli, xlog_seg_size))
if (wal_contains_lsn(wal_segment_dir, lsn, tli,
instance_config.xlog_seg_size))
/* Target LSN was found */
{
elog(LOG, "Found LSN: %X/%X", (uint32) (lsn >> 32), (uint32) lsn);
@ -1650,11 +1673,12 @@ wait_replica_wal_lsn(XLogRecPtr lsn, bool is_start_backup)
elog(INFO, "Wait for target LSN %X/%X to be received by replica",
(uint32) (lsn >> 32), (uint32) lsn);
if (replica_timeout > 0 && try_count > replica_timeout)
if (instance_config.replica_timeout > 0 &&
try_count > instance_config.replica_timeout)
elog(ERROR, "Target LSN %X/%X could not be recevied by replica "
"in %d seconds",
(uint32) (lsn >> 32), (uint32) lsn,
replica_timeout);
instance_config.replica_timeout);
}
}
@ -1962,7 +1986,8 @@ pg_stop_backup(pgBackup *backup)
elog(LOG, "Getting the Recovery Time from WAL");
if (!read_recovery_info(xlog_path, backup->tli, xlog_seg_size,
if (!read_recovery_info(xlog_path, backup->tli,
instance_config.xlog_seg_size,
backup->start_lsn, backup->stop_lsn,
&backup->recovery_time, &backup->recovery_xid))
{
@ -2134,7 +2159,8 @@ backup_files(void *arg)
if (!backup_data_file(arguments, to_path, file,
arguments->prev_start_lsn,
current.backup_mode,
compress_alg, compress_level))
instance_config.compress_alg,
instance_config.compress_level))
{
file->write_size = BYTES_INVALID;
elog(VERBOSE, "File \"%s\" was not copied to backup", file->path);
@ -2336,9 +2362,9 @@ process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
rel_path = relpathperm(rnode, forknum);
if (segno > 0)
path = psprintf("%s/%s.%u", pgdata, rel_path, segno);
path = psprintf("%s/%s.%u", instance_config.pgdata, rel_path, segno);
else
path = psprintf("%s/%s", pgdata, rel_path);
path = psprintf("%s/%s", instance_config.pgdata, rel_path);
pg_free(rel_path);
@ -2578,7 +2604,7 @@ StreamLog(void *arg)
/*
* Always start streaming at the beginning of a segment
*/
startpos -= startpos % xlog_seg_size;
startpos -= startpos % instance_config.xlog_seg_size;
/* Initialize timeout */
stream_stop_timeout = 0;
@ -2692,7 +2718,10 @@ pg_ptrack_get_block(backup_files_arg *arguments,
if (arguments->backup_conn == NULL)
{
arguments->backup_conn = pgut_connect(pgut_dbname);
arguments->backup_conn = pgut_connect(instance_config.pghost,
instance_config.pgport,
instance_config.pgdatabase,
instance_config.pguser);
}
if (arguments->cancel_conn == NULL)

View File

@ -15,6 +15,8 @@
#include <sys/stat.h>
#include <unistd.h>
#include "utils/configuration.h"
static const char *backupModes[] = {"", "PAGE", "PTRACK", "DELTA", "FULL"};
static pgBackup *readBackupControlFile(const char *path);
@ -559,7 +561,7 @@ readBackupControlFile(const char *path)
char *compress_alg = NULL;
int parsed_options;
pgut_option options[] =
ConfigOption options[] =
{
{'s', 0, "backup-mode", &backup_mode, SOURCE_FILE_STRICT},
{'u', 0, "timelineid", &backup->tli, SOURCE_FILE_STRICT},
@ -594,7 +596,7 @@ readBackupControlFile(const char *path)
return NULL;
}
parsed_options = pgut_readopt(path, options, WARNING, true);
parsed_options = config_read_opt(path, options, WARNING, true);
if (parsed_options == 0)
{

View File

@ -9,124 +9,271 @@
#include "pg_probackup.h"
#include "utils/configuration.h"
#include "utils/json.h"
static void opt_log_level_console(pgut_option *opt, const char *arg);
static void opt_log_level_file(pgut_option *opt, const char *arg);
static void opt_compress_alg(pgut_option *opt, const char *arg);
static void assign_log_level_console(ConfigOption *opt, const char *arg);
static void assign_log_level_file(ConfigOption *opt, const char *arg);
static void assign_compress_alg(ConfigOption *opt, const char *arg);
static char *get_log_level_console(ConfigOption *opt);
static char *get_log_level_file(ConfigOption *opt);
static char *get_compress_alg(ConfigOption *opt);
static void show_configure_start(void);
static void show_configure_end(void);
static void show_configure(pgBackupConfig *config);
static void show_configure_json(pgBackupConfig *config);
static void show_configure_plain(ConfigOption *opt);
static void show_configure_json(ConfigOption *opt);
static pgBackupConfig *cur_config = NULL;
#define ARCHIVE_TIMEOUT_DEFAULT 300
#define REPLICA_TIMEOUT_DEFAULT 300
#define RETENTION_REDUNDANCY_DEFAULT 0
#define RETENTION_WINDOW_DEFAULT 0
#define OPTION_INSTANCE_GROUP "Backup instance information"
#define OPTION_CONN_GROUP "Connection parameters"
#define OPTION_REPLICA_GROUP "Replica parameters"
#define OPTION_ARCHIVE_GROUP "Archive parameters"
#define OPTION_LOG_GROUP "Logging parameters"
#define OPTION_RETENTION_GROUP "Retention parameters"
#define OPTION_COMPRESS_GROUP "Compression parameters"
/*
* Short name should be non-printable ASCII character.
*/
ConfigOption instance_options[] =
{
/* Instance options */
{
's', 'D', "pgdata",
&instance_config.pgdata, SOURCE_CMD, 0,
OPTION_INSTANCE_GROUP, 0, option_get_value
},
{
'U', 200, "system-identifier",
&instance_config.system_identifier, SOURCE_FILE_STRICT, 0,
OPTION_INSTANCE_GROUP, 0, option_get_value
},
#if PG_VERSION_NUM >= 110000
{
'u', 201, "xlog-seg-size",
&instance_config.xlog_seg_size, SOURCE_FILE_STRICT, 0,
OPTION_INSTANCE_GROUP, 0, option_get_value
},
#endif
/* Connection options */
{
's', 'd', "pgdatabase",
&instance_config.pgdatabase, SOURCE_CMD, 0,
OPTION_CONN_GROUP, 0, option_get_value
},
{
's', 'h', "pghost",
&instance_config.pghost, SOURCE_CMD, 0,
OPTION_CONN_GROUP, 0, option_get_value
},
{
's', 'p', "pgport",
&instance_config.pgport, SOURCE_CMD, 0,
OPTION_CONN_GROUP, 0, option_get_value
},
{
's', 'U', "pguser",
&instance_config.pguser, SOURCE_CMD, 0,
OPTION_CONN_GROUP, 0, option_get_value
},
/* Replica options */
{
's', 202, "master-db",
&instance_config.master_db, SOURCE_CMD, 0,
OPTION_REPLICA_GROUP, 0, option_get_value
},
{
's', 203, "master-host",
&instance_config.master_host, SOURCE_CMD, 0,
OPTION_REPLICA_GROUP, 0, option_get_value
},
{
's', 204, "master-port",
&instance_config.master_port, SOURCE_CMD, 0,
OPTION_REPLICA_GROUP, 0, option_get_value
},
{
's', 205, "master-user",
&instance_config.master_user, SOURCE_CMD, 0,
OPTION_REPLICA_GROUP, 0, option_get_value
},
{
'u', 206, "replica-timeout",
&instance_config.replica_timeout, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_REPLICA_GROUP, OPTION_UNIT_S, option_get_value
},
/* Archive options */
{
'u', 207, "archive-timeout",
&instance_config.archive_timeout, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_ARCHIVE_GROUP, OPTION_UNIT_S, option_get_value
},
/* Logging options */
{
'f', 208, "log-level-console",
assign_log_level_console, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, get_log_level_console
},
{
'f', 209, "log-level-file",
assign_log_level_file, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, get_log_level_file
},
{
's', 210, "log-filename",
&instance_config.logger.log_filename, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 211, "error-log-filename",
&instance_config.logger.error_log_filename, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 212, "log-directory",
&instance_config.logger.log_directory, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
'U', 213, "log-rotation-size",
&instance_config.logger.log_rotation_size, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_LOG_GROUP, OPTION_UNIT_KB, option_get_value
},
{
'U', 214, "log-rotation-age",
&instance_config.logger.log_rotation_age, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_LOG_GROUP, OPTION_UNIT_MS, option_get_value
},
/* Retention options */
{
'u', 215, "retention-redundancy",
&instance_config.retention_redundancy, SOURCE_CMD, 0,
OPTION_RETENTION_GROUP, 0, option_get_value
},
{
'u', 216, "retention-window",
&instance_config.retention_window, SOURCE_CMD, 0,
OPTION_RETENTION_GROUP, 0, option_get_value
},
/* Compression options */
{
'f', 217, "compress-algorithm",
assign_compress_alg, SOURCE_CMD, 0,
OPTION_COMPRESS_GROUP, 0, get_compress_alg
},
{
'u', 218, "compress-level",
&instance_config.compress_level, SOURCE_CMD, 0,
OPTION_COMPRESS_GROUP, 0, option_get_value
},
{ 0 }
};
/* An instance configuration with default options */
InstanceConfig instance_config;
static PQExpBufferData show_buf;
static int32 json_level = 0;
static const char *current_group = NULL;
/*
* All this code needs refactoring.
* Show configure options including default values.
*/
/* Set configure options */
int
do_configure(bool show_only)
void
do_show_config(void)
{
pgBackupConfig *config = readBackupCatalogConfigFile();
if (pgdata)
config->pgdata = pgdata;
if (pgut_dbname)
config->pgdatabase = pgut_dbname;
if (host)
config->pghost = host;
if (port)
config->pgport = port;
if (username)
config->pguser = username;
int i;
if (master_host)
config->master_host = master_host;
if (master_port)
config->master_port = master_port;
if (master_db)
config->master_db = master_db;
if (master_user)
config->master_user = master_user;
show_configure_start();
if (replica_timeout)
config->replica_timeout = replica_timeout;
for (i = 0; instance_options[i].type; i++)
{
if (show_format == SHOW_PLAIN)
show_configure_plain(&instance_options[i]);
else
show_configure_json(&instance_options[i]);
}
if (archive_timeout)
config->archive_timeout = archive_timeout;
show_configure_end();
}
if (log_level_console)
config->log_level_console = log_level_console;
if (log_level_file)
config->log_level_file = log_level_file;
if (log_filename)
config->log_filename = log_filename;
if (error_log_filename)
config->error_log_filename = error_log_filename;
if (log_directory)
config->log_directory = log_directory;
if (log_rotation_size)
config->log_rotation_size = log_rotation_size;
if (log_rotation_age)
config->log_rotation_age = log_rotation_age;
/*
* Save configure options into BACKUP_CATALOG_CONF_FILE. Do not save default
* values into the file.
*/
void
do_set_config(void)
{
char path[MAXPGPATH];
FILE *fp;
int i;
if (retention_redundancy)
config->retention_redundancy = retention_redundancy;
if (retention_window)
config->retention_window = retention_window;
join_path_components(path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);
fp = fopen(path, "wt");
if (fp == NULL)
elog(ERROR, "cannot create %s: %s",
BACKUP_CATALOG_CONF_FILE, strerror(errno));
if (compress_alg)
config->compress_alg = compress_alg;
if (compress_level)
config->compress_level = compress_level;
current_group = NULL;
if (show_only)
show_configure(config);
else
writeBackupCatalogConfigFile(config);
for (i = 0; instance_options[i].type; i++)
{
ConfigOption *opt = &instance_options[i];
char *value;
return 0;
/* Save only options from command line */
if (opt->source != SOURCE_CMD &&
/* ...or options from the previous configure file */
opt->source != SOURCE_FILE && opt->source != SOURCE_FILE_STRICT)
continue;
value = opt->get_value(opt);
if (value == NULL)
continue;
if (current_group == NULL || strcmp(opt->group, current_group) != 0)
{
current_group = opt->group;
fprintf(fp, "# %s\n", current_group);
}
fprintf(fp, "%s = %s\n", opt->lname, value);
pfree(value);
}
fclose(fp);
}
void
pgBackupConfigInit(pgBackupConfig *config)
init_config(InstanceConfig *config)
{
config->system_identifier = 0;
MemSet(config, 0, sizeof(InstanceConfig));
/*
* Starting from PostgreSQL 11 WAL segment size may vary. Prior to
* PostgreSQL 10 xlog_seg_size is equal to XLOG_SEG_SIZE.
*/
#if PG_VERSION_NUM >= 110000
config->xlog_seg_size = 0;
#else
config->xlog_seg_size = XLOG_SEG_SIZE;
#endif
config->pgdata = NULL;
config->pgdatabase = NULL;
config->pghost = NULL;
config->pgport = NULL;
config->pguser = NULL;
config->master_host = NULL;
config->master_port = NULL;
config->master_db = NULL;
config->master_user = NULL;
config->replica_timeout = REPLICA_TIMEOUT_DEFAULT;
config->archive_timeout = ARCHIVE_TIMEOUT_DEFAULT;
config->log_level_console = LOG_LEVEL_CONSOLE_DEFAULT;
config->log_level_file = LOG_LEVEL_FILE_DEFAULT;
config->log_filename = LOG_FILENAME_DEFAULT;
config->error_log_filename = NULL;
config->log_directory = LOG_DIRECTORY_DEFAULT;
config->log_rotation_size = LOG_ROTATION_SIZE_DEFAULT;
config->log_rotation_age = LOG_ROTATION_AGE_DEFAULT;
/* Copy logger defaults */
config->logger = logger_config;
config->retention_redundancy = RETENTION_REDUNDANCY_DEFAULT;
config->retention_window = RETENTION_WINDOW_DEFAULT;
@ -135,198 +282,40 @@ pgBackupConfigInit(pgBackupConfig *config)
config->compress_level = COMPRESS_LEVEL_DEFAULT;
}
void
writeBackupCatalogConfig(FILE *out, pgBackupConfig *config)
static void
assign_log_level_console(ConfigOption *opt, const char *arg)
{
uint64 res;
const char *unit;
fprintf(out, "#Backup instance info\n");
fprintf(out, "PGDATA = %s\n", config->pgdata);
fprintf(out, "system-identifier = " UINT64_FORMAT "\n", config->system_identifier);
#if PG_VERSION_NUM >= 110000
fprintf(out, "xlog-seg-size = %u\n", config->xlog_seg_size);
#endif
fprintf(out, "#Connection parameters:\n");
if (config->pgdatabase)
fprintf(out, "PGDATABASE = %s\n", config->pgdatabase);
if (config->pghost)
fprintf(out, "PGHOST = %s\n", config->pghost);
if (config->pgport)
fprintf(out, "PGPORT = %s\n", config->pgport);
if (config->pguser)
fprintf(out, "PGUSER = %s\n", config->pguser);
fprintf(out, "#Replica parameters:\n");
if (config->master_host)
fprintf(out, "master-host = %s\n", config->master_host);
if (config->master_port)
fprintf(out, "master-port = %s\n", config->master_port);
if (config->master_db)
fprintf(out, "master-db = %s\n", config->master_db);
if (config->master_user)
fprintf(out, "master-user = %s\n", config->master_user);
convert_from_base_unit_u(config->replica_timeout, OPTION_UNIT_MS,
&res, &unit);
fprintf(out, "replica-timeout = " UINT64_FORMAT "%s\n", res, unit);
fprintf(out, "#Archive parameters:\n");
convert_from_base_unit_u(config->archive_timeout, OPTION_UNIT_MS,
&res, &unit);
fprintf(out, "archive-timeout = " UINT64_FORMAT "%s\n", res, unit);
fprintf(out, "#Logging parameters:\n");
fprintf(out, "log-level-console = %s\n", deparse_log_level(config->log_level_console));
fprintf(out, "log-level-file = %s\n", deparse_log_level(config->log_level_file));
fprintf(out, "log-filename = %s\n", config->log_filename);
if (config->error_log_filename)
fprintf(out, "error-log-filename = %s\n", config->error_log_filename);
if (strcmp(config->log_directory, LOG_DIRECTORY_DEFAULT) == 0)
fprintf(out, "log-directory = %s/%s\n", backup_path, config->log_directory);
else
fprintf(out, "log-directory = %s\n", config->log_directory);
/* Convert values from base unit */
convert_from_base_unit_u(config->log_rotation_size, OPTION_UNIT_KB,
&res, &unit);
fprintf(out, "log-rotation-size = " UINT64_FORMAT "%s\n", res, (res)?unit:"KB");
convert_from_base_unit_u(config->log_rotation_age, OPTION_UNIT_MS,
&res, &unit);
fprintf(out, "log-rotation-age = " UINT64_FORMAT "%s\n", res, (res)?unit:"min");
fprintf(out, "#Retention parameters:\n");
fprintf(out, "retention-redundancy = %u\n", config->retention_redundancy);
fprintf(out, "retention-window = %u\n", config->retention_window);
fprintf(out, "#Compression parameters:\n");
fprintf(out, "compress-algorithm = %s\n", deparse_compress_alg(config->compress_alg));
fprintf(out, "compress-level = %d\n", config->compress_level);
}
void
writeBackupCatalogConfigFile(pgBackupConfig *config)
{
char path[MAXPGPATH];
FILE *fp;
join_path_components(path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);
fp = fopen(path, "wt");
if (fp == NULL)
elog(ERROR, "cannot create %s: %s",
BACKUP_CATALOG_CONF_FILE, strerror(errno));
writeBackupCatalogConfig(fp, config);
fclose(fp);
}
pgBackupConfig*
readBackupCatalogConfigFile(void)
{
pgBackupConfig *config = pgut_new(pgBackupConfig);
char path[MAXPGPATH];
pgut_option options[] =
{
/* retention options */
{ 'u', 0, "retention-redundancy", &(config->retention_redundancy),SOURCE_FILE_STRICT },
{ 'u', 0, "retention-window", &(config->retention_window), SOURCE_FILE_STRICT },
/* compression options */
{ 'f', 0, "compress-algorithm", opt_compress_alg, SOURCE_CMDLINE },
{ 'u', 0, "compress-level", &(config->compress_level), SOURCE_CMDLINE },
/* logging options */
{ 'f', 0, "log-level-console", opt_log_level_console, SOURCE_CMDLINE },
{ 'f', 0, "log-level-file", opt_log_level_file, SOURCE_CMDLINE },
{ 's', 0, "log-filename", &(config->log_filename), SOURCE_CMDLINE },
{ 's', 0, "error-log-filename", &(config->error_log_filename), SOURCE_CMDLINE },
{ 's', 0, "log-directory", &(config->log_directory), SOURCE_CMDLINE },
{ 'U', 0, "log-rotation-size", &(config->log_rotation_size), SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_KB },
{ 'U', 0, "log-rotation-age", &(config->log_rotation_age), SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_MS },
/* connection options */
{ 's', 0, "pgdata", &(config->pgdata), SOURCE_FILE_STRICT },
{ 's', 0, "pgdatabase", &(config->pgdatabase), SOURCE_FILE_STRICT },
{ 's', 0, "pghost", &(config->pghost), SOURCE_FILE_STRICT },
{ 's', 0, "pgport", &(config->pgport), SOURCE_FILE_STRICT },
{ 's', 0, "pguser", &(config->pguser), SOURCE_FILE_STRICT },
/* replica options */
{ 's', 0, "master-host", &(config->master_host), SOURCE_FILE_STRICT },
{ 's', 0, "master-port", &(config->master_port), SOURCE_FILE_STRICT },
{ 's', 0, "master-db", &(config->master_db), SOURCE_FILE_STRICT },
{ 's', 0, "master-user", &(config->master_user), SOURCE_FILE_STRICT },
{ 'u', 0, "replica-timeout", &(config->replica_timeout), SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S },
/* other options */
{ 'U', 0, "system-identifier", &(config->system_identifier), SOURCE_FILE_STRICT },
#if PG_VERSION_NUM >= 110000
{'u', 0, "xlog-seg-size", &config->xlog_seg_size, SOURCE_FILE_STRICT},
#endif
/* archive options */
{ 'u', 0, "archive-timeout", &(config->archive_timeout), SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S },
{0}
};
cur_config = config;
join_path_components(path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);
pgBackupConfigInit(config);
pgut_readopt(path, options, ERROR, true);
#if PG_VERSION_NUM >= 110000
if (!IsValidWalSegSize(config->xlog_seg_size))
elog(ERROR, "Invalid WAL segment size %u", config->xlog_seg_size);
#endif
return config;
}
/*
* Read xlog-seg-size from BACKUP_CATALOG_CONF_FILE.
*/
uint32
get_config_xlog_seg_size(void)
{
#if PG_VERSION_NUM >= 110000
char path[MAXPGPATH];
uint32 seg_size;
pgut_option options[] =
{
{'u', 0, "xlog-seg-size", &seg_size, SOURCE_FILE_STRICT},
{0}
};
join_path_components(path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);
pgut_readopt(path, options, ERROR, false);
if (!IsValidWalSegSize(seg_size))
elog(ERROR, "Invalid WAL segment size %u", seg_size);
return seg_size;
#else
return (uint32) XLOG_SEG_SIZE;
#endif
instance_config.logger.log_level_console = parse_log_level(arg);
}
static void
opt_log_level_console(pgut_option *opt, const char *arg)
assign_log_level_file(ConfigOption *opt, const char *arg)
{
cur_config->log_level_console = parse_log_level(arg);
instance_config.logger.log_level_file = parse_log_level(arg);
}
static void
opt_log_level_file(pgut_option *opt, const char *arg)
assign_compress_alg(ConfigOption *opt, const char *arg)
{
cur_config->log_level_file = parse_log_level(arg);
instance_config.compress_alg = parse_compress_alg(arg);
}
static void
opt_compress_alg(pgut_option *opt, const char *arg)
static char *
get_log_level_console(ConfigOption *opt)
{
cur_config->compress_alg = parse_compress_alg(arg);
return pstrdup(deparse_log_level(instance_config.logger.log_level_console));
}
static char *
get_log_level_file(ConfigOption *opt)
{
return pstrdup(deparse_log_level(instance_config.logger.log_level_file));
}
static char *
get_compress_alg(ConfigOption *opt)
{
return pstrdup(deparse_compress_alg(instance_config.compress_alg));
}
/*
@ -335,12 +324,15 @@ opt_compress_alg(pgut_option *opt, const char *arg)
static void
show_configure_start(void)
{
if (show_format == SHOW_PLAIN)
return;
/* For now we need buffer only for JSON format */
json_level = 0;
initPQExpBuffer(&show_buf);
if (show_format == SHOW_PLAIN)
current_group = NULL;
else
{
json_level = 0;
json_add(&show_buf, JT_BEGIN_OBJECT, &json_level);
}
}
/*
@ -350,28 +342,38 @@ static void
show_configure_end(void)
{
if (show_format == SHOW_PLAIN)
return;
current_group = NULL;
else
{
json_add(&show_buf, JT_END_OBJECT, &json_level);
appendPQExpBufferChar(&show_buf, '\n');
}
fputs(show_buf.data, stdout);
termPQExpBuffer(&show_buf);
}
/*
* Show configure information of pg_probackup.
* Plain output.
*/
static void
show_configure(pgBackupConfig *config)
show_configure_plain(ConfigOption *opt)
{
show_configure_start();
char *value;
if (show_format == SHOW_PLAIN)
writeBackupCatalogConfig(stdout, config);
else
show_configure_json(config);
value = opt->get_value(opt);
if (value == NULL)
return;
show_configure_end();
if (current_group == NULL || strcmp(opt->group, current_group) != 0)
{
current_group = opt->group;
appendPQExpBuffer(&show_buf, "# %s\n", current_group);
}
appendPQExpBuffer(&show_buf, "%s = %s\n", opt->lname, value);
pfree(value);
}
/*
@ -379,109 +381,15 @@ show_configure(pgBackupConfig *config)
*/
static void
show_configure_json(pgBackupConfig *config)
show_configure_json(ConfigOption *opt)
{
PQExpBuffer buf = &show_buf;
uint64 res;
const char *unit;
char *value;
json_add(buf, JT_BEGIN_OBJECT, &json_level);
value = opt->get_value(opt);
if (value == NULL)
return;
json_add_value(buf, "pgdata", config->pgdata, json_level, false);
json_add_key(buf, "system-identifier", json_level, true);
appendPQExpBuffer(buf, UINT64_FORMAT, config->system_identifier);
#if PG_VERSION_NUM >= 110000
json_add_key(buf, "xlog-seg-size", json_level, true);
appendPQExpBuffer(buf, "%u", config->xlog_seg_size);
#endif
/* Connection parameters */
if (config->pgdatabase)
json_add_value(buf, "pgdatabase", config->pgdatabase, json_level, true);
if (config->pghost)
json_add_value(buf, "pghost", config->pghost, json_level, true);
if (config->pgport)
json_add_value(buf, "pgport", config->pgport, json_level, true);
if (config->pguser)
json_add_value(buf, "pguser", config->pguser, json_level, true);
/* Replica parameters */
if (config->master_host)
json_add_value(buf, "master-host", config->master_host, json_level,
true);
if (config->master_port)
json_add_value(buf, "master-port", config->master_port, json_level,
true);
if (config->master_db)
json_add_value(buf, "master-db", config->master_db, json_level, true);
if (config->master_user)
json_add_value(buf, "master-user", config->master_user, json_level,
true);
json_add_key(buf, "replica-timeout", json_level, true);
convert_from_base_unit_u(config->replica_timeout, OPTION_UNIT_MS,
&res, &unit);
appendPQExpBuffer(buf, UINT64_FORMAT "%s", res, unit);
/* Archive parameters */
json_add_key(buf, "archive-timeout", json_level, true);
convert_from_base_unit_u(config->archive_timeout, OPTION_UNIT_MS,
&res, &unit);
appendPQExpBuffer(buf, UINT64_FORMAT "%s", res, unit);
/* Logging parameters */
json_add_value(buf, "log-level-console",
deparse_log_level(config->log_level_console), json_level,
true);
json_add_value(buf, "log-level-file",
deparse_log_level(config->log_level_file), json_level,
true);
json_add_value(buf, "log-filename", config->log_filename, json_level,
true);
if (config->error_log_filename)
json_add_value(buf, "error-log-filename", config->error_log_filename,
json_level, true);
if (strcmp(config->log_directory, LOG_DIRECTORY_DEFAULT) == 0)
{
char log_directory_fullpath[MAXPGPATH];
sprintf(log_directory_fullpath, "%s/%s",
backup_path, config->log_directory);
json_add_value(buf, "log-directory", log_directory_fullpath,
json_level, true);
}
else
json_add_value(buf, "log-directory", config->log_directory,
json_level, true);
json_add_key(buf, "log-rotation-size", json_level, true);
convert_from_base_unit_u(config->log_rotation_size, OPTION_UNIT_KB,
&res, &unit);
appendPQExpBuffer(buf, UINT64_FORMAT "%s", res, (res)?unit:"KB");
json_add_key(buf, "log-rotation-age", json_level, true);
convert_from_base_unit_u(config->log_rotation_age, OPTION_UNIT_MS,
&res, &unit);
appendPQExpBuffer(buf, UINT64_FORMAT "%s", res, (res)?unit:"min");
/* Retention parameters */
json_add_key(buf, "retention-redundancy", json_level, true);
appendPQExpBuffer(buf, "%u", config->retention_redundancy);
json_add_key(buf, "retention-window", json_level, true);
appendPQExpBuffer(buf, "%u", config->retention_window);
/* Compression parameters */
json_add_value(buf, "compress-algorithm",
deparse_compress_alg(config->compress_alg), json_level,
true);
json_add_key(buf, "compress-level", json_level, true);
appendPQExpBuffer(buf, "%d", config->compress_level);
json_add(buf, JT_END_OBJECT, &json_level);
json_add_value(&show_buf, opt->lname, value, json_level,
opt->type == 's' || opt->flags & OPTION_UNIT);
pfree(value);
}

View File

@ -1122,9 +1122,10 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", gz_to_path);
gz_out = gzopen(to_path_temp, PG_BINARY_W);
if (gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
if (gzsetparams(gz_out, instance_config.compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
elog(ERROR, "Cannot set compression level %d to file \"%s\": %s",
compress_level, to_path_temp, get_gz_error(gz_out, errno));
instance_config.compress_level, to_path_temp,
get_gz_error(gz_out, errno));
to_path_p = gz_to_path;
}

View File

@ -109,7 +109,7 @@ do_delete(time_t backup_id)
}
}
delete_walfiles(oldest_lsn, oldest_tli, xlog_seg_size);
delete_walfiles(oldest_lsn, oldest_tli, instance_config.xlog_seg_size);
}
/* cleanup */
@ -125,9 +125,7 @@ int
do_retention_purge(void)
{
parray *backup_list;
uint32 backup_num;
size_t i;
time_t days_threshold = time(NULL) - (retention_window * 60 * 60 * 24);
XLogRecPtr oldest_lsn = InvalidXLogRecPtr;
TimeLineID oldest_tli = 0;
bool keep_next_backup = true; /* Do not delete first full backup */
@ -135,13 +133,13 @@ do_retention_purge(void)
if (delete_expired)
{
if (retention_redundancy > 0)
elog(LOG, "REDUNDANCY=%u", retention_redundancy);
if (retention_window > 0)
elog(LOG, "WINDOW=%u", retention_window);
if (instance_config.retention_redundancy > 0)
elog(LOG, "REDUNDANCY=%u", instance_config.retention_redundancy);
if (instance_config.retention_window > 0)
elog(LOG, "WINDOW=%u", instance_config.retention_window);
if (retention_redundancy == 0
&& retention_window == 0)
if (instance_config.retention_redundancy == 0
&& instance_config.retention_window == 0)
{
elog(WARNING, "Retention policy is not set");
if (!delete_wal)
@ -162,9 +160,15 @@ do_retention_purge(void)
/* Find target backups to be deleted */
if (delete_expired &&
(retention_redundancy > 0 || retention_window > 0))
(instance_config.retention_redundancy > 0 ||
instance_config.retention_window > 0))
{
backup_num = 0;
time_t days_threshold;
uint32 backup_num = 0;
days_threshold = time(NULL) -
(instance_config.retention_window * 60 * 60 * 24);
for (i = 0; i < parray_num(backup_list); i++)
{
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
@ -182,8 +186,9 @@ do_retention_purge(void)
/* Evaluate retention_redundancy if this backup is eligible for removal */
if (keep_next_backup ||
retention_redundancy >= backup_num_evaluate + 1 ||
(retention_window > 0 && backup->recovery_time >= days_threshold))
instance_config.retention_redundancy >= backup_num_evaluate + 1 ||
(instance_config.retention_window > 0 &&
backup->recovery_time >= days_threshold))
{
/* Save LSN and Timeline to remove unnecessary WAL segments */
oldest_lsn = backup->start_lsn;
@ -226,7 +231,7 @@ do_retention_purge(void)
/* Purge WAL files */
if (delete_wal)
{
delete_walfiles(oldest_lsn, oldest_tli, xlog_seg_size);
delete_walfiles(oldest_lsn, oldest_tli, instance_config.xlog_seg_size);
}
/* Cleanup */
@ -439,7 +444,7 @@ do_delete_instance(void)
parray_free(backup_list);
/* Delete all wal files. */
delete_walfiles(InvalidXLogRecPtr, 0, xlog_seg_size);
delete_walfiles(InvalidXLogRecPtr, 0, instance_config.xlog_seg_size);
/* Delete backup instance config file */
join_path_components(instance_config_path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);

View File

@ -19,6 +19,8 @@
#include <sys/stat.h>
#include <dirent.h>
#include "utils/configuration.h"
/*
* The contents of these directories are removed or recreated during server
* start so they are not included in backups. The directories themselves are
@ -379,7 +381,8 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
join_path_components(path, backup_instance_path, PG_BLACK_LIST);
/* List files with black list */
if (root && pgdata && strcmp(root, pgdata) == 0 && fileExists(path))
if (root && instance_config.pgdata &&
strcmp(root, instance_config.pgdata) == 0 && fileExists(path))
{
FILE *black_list_file = NULL;
char buf[MAXPGPATH * 2];
@ -393,7 +396,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
while (fgets(buf, lengthof(buf), black_list_file) != NULL)
{
join_path_components(black_item, pgdata, buf);
join_path_components(black_item, instance_config.pgdata, buf);
if (black_item[strlen(black_item) - 1] == '\n')
black_item[strlen(black_item) - 1] = '\0';
@ -844,7 +847,7 @@ get_tablespace_created(const char *link)
* Copy of function tablespace_list_append() from pg_basebackup.c.
*/
void
opt_tablespace_map(pgut_option *opt, const char *arg)
opt_tablespace_map(ConfigOption *opt, const char *arg)
{
TablespaceListCell *cell = pgut_new(TablespaceListCell);
char *dst;
@ -1121,7 +1124,8 @@ check_tablespace_mapping(pgBackup *backup)
/* Sort links by the path of a linked file*/
parray_qsort(links, pgFileCompareLinked);
if (log_level_console <= LOG || log_level_file <= LOG)
if (logger_config.log_level_console <= LOG ||
logger_config.log_level_file <= LOG)
elog(LOG, "check tablespace directories of backup %s",
base36enc(backup->start_time));

View File

@ -21,7 +21,7 @@ do_init(void)
{
char path[MAXPGPATH];
char arclog_path_dir[MAXPGPATH];
int results;
int results;
results = pg_check_dir(backup_path);
if (results == 4) /* exists and not empty*/
@ -54,17 +54,16 @@ do_add_instance(void)
char path[MAXPGPATH];
char arclog_path_dir[MAXPGPATH];
struct stat st;
pgBackupConfig *config = pgut_new(pgBackupConfig);
/* PGDATA is always required */
if (pgdata == NULL)
if (instance_config.pgdata == NULL)
elog(ERROR, "Required parameter not specified: PGDATA "
"(-D, --pgdata)");
/* Read system_identifier from PGDATA */
system_identifier = get_system_identifier(pgdata);
instance_config.system_identifier = get_system_identifier(instance_config.pgdata);
/* Starting from PostgreSQL 11 read WAL segment size from PGDATA */
xlog_seg_size = get_xlog_seg_size(pgdata);
instance_config.xlog_seg_size = get_xlog_seg_size(instance_config.pgdata);
/* Ensure that all root directories already exist */
if (access(backup_path, F_OK) != 0)
@ -93,14 +92,19 @@ do_add_instance(void)
dir_create_dir(arclog_path, DIR_PERMISSION);
/*
* Wite initial config. system-identifier and pgdata are set in
* init subcommand and will never be updated.
* Write initial configuration file.
* system-identifier, xlog-seg-size and pgdata are set in init subcommand
* and will never be updated.
*
* We need to manually set options source to save them to the configuration
* file.
*/
pgBackupConfigInit(config);
config->system_identifier = system_identifier;
config->xlog_seg_size = xlog_seg_size;
config->pgdata = pgdata;
writeBackupCatalogConfigFile(config);
config_set_opt(instance_options, &instance_config.system_identifier,
SOURCE_FILE);
config_set_opt(instance_options, &instance_config.xlog_seg_size,
SOURCE_FILE);
/* pgdata was set through command line */
do_set_config();
elog(INFO, "Instance '%s' successfully inited", instance_name);
return 0;

View File

@ -319,9 +319,9 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
}
/* compute size of wal files of this backup stored in the archive */
if (!to_backup->stream)
to_backup->wal_bytes = xlog_seg_size *
(to_backup->stop_lsn / xlog_seg_size -
to_backup->start_lsn / xlog_seg_size + 1);
to_backup->wal_bytes = instance_config.xlog_seg_size *
(to_backup->stop_lsn / instance_config.xlog_seg_size -
to_backup->start_lsn / instance_config.xlog_seg_size + 1);
else
to_backup->wal_bytes = BYTES_INVALID;

View File

@ -227,7 +227,7 @@ doExtractPageMap(void *arg)
#endif
if (xlogreader == NULL)
elog(ERROR, "Thread [%d]: out of memory", private_data->thread_num);
xlogreader->system_identifier = system_identifier;
xlogreader->system_identifier = instance_config.system_identifier;
found = XLogFindNextRecord(xlogreader, extract_arg->startpoint);
@ -976,7 +976,7 @@ InitXLogPageRead(XLogPageReadPrivate *private_data, const char *archivedir,
#endif
if (xlogreader == NULL)
elog(ERROR, "out of memory");
xlogreader->system_identifier = system_identifier;
xlogreader->system_identifier = instance_config.system_identifier;
}
return xlogreader;

View File

@ -15,6 +15,7 @@
#include <sys/stat.h>
#include "utils/configuration.h"
#include "utils/thread.h"
const char *PROGRAM_VERSION = "2.0.23";
@ -41,7 +42,6 @@ typedef enum ProbackupSubcmd
/* directory options */
char *backup_path = NULL;
char *pgdata = NULL;
/*
* path or to the data files in the backup catalog
* $BACKUP_PATH/backups/instance_name
@ -66,13 +66,6 @@ char *replication_slot = NULL;
bool backup_logs = false;
bool smooth_checkpoint;
bool is_remote_backup = false;
/* Wait timeout for WAL segment archiving */
uint32 archive_timeout = ARCHIVE_TIMEOUT_DEFAULT;
const char *master_db = NULL;
const char *master_host = NULL;
const char *master_port= NULL;
const char *master_user = NULL;
uint32 replica_timeout = REPLICA_TIMEOUT_DEFAULT;
/* restore options */
static char *target_time;
@ -94,32 +87,13 @@ bool skip_block_validation = false;
/* delete options */
bool delete_wal = false;
bool delete_expired = false;
bool apply_to_all = false;
bool force_delete = false;
/* retention options */
uint32 retention_redundancy = 0;
uint32 retention_window = 0;
/* compression options */
CompressAlg compress_alg = COMPRESS_ALG_DEFAULT;
int compress_level = COMPRESS_LEVEL_DEFAULT;
bool compress_shortcut = false;
/* other options */
char *instance_name;
uint64 system_identifier = 0;
/*
* Starting from PostgreSQL 11 WAL segment size may vary. Prior to
* PostgreSQL 10 xlog_seg_size is equal to XLOG_SEG_SIZE.
*/
#if PG_VERSION_NUM >= 110000
uint32 xlog_seg_size = 0;
#else
uint32 xlog_seg_size = XLOG_SEG_SIZE;
#endif
/* archive push options */
static char *wal_file_path;
@ -135,93 +109,64 @@ static ProbackupSubcmd backup_subcmd = NO_CMD;
static bool help_opt = false;
static void opt_backup_mode(pgut_option *opt, const char *arg);
static void opt_log_level_console(pgut_option *opt, const char *arg);
static void opt_log_level_file(pgut_option *opt, const char *arg);
static void opt_compress_alg(pgut_option *opt, const char *arg);
static void opt_show_format(pgut_option *opt, const char *arg);
static void opt_backup_mode(ConfigOption *opt, const char *arg);
static void opt_show_format(ConfigOption *opt, const char *arg);
static void compress_init(void);
static pgut_option options[] =
/*
* Short name should be non-printable ASCII character.
*/
static ConfigOption cmd_options[] =
{
/* directory options */
{ 'b', 1, "help", &help_opt, SOURCE_CMDLINE },
{ 's', 'D', "pgdata", &pgdata, SOURCE_CMDLINE },
{ 's', 'B', "backup-path", &backup_path, SOURCE_CMDLINE },
{ 'b', 130, "help", &help_opt, SOURCE_CMD_STRICT },
{ 's', 'B', "backup-path", &backup_path, SOURCE_CMD_STRICT },
/* common options */
{ 'u', 'j', "threads", &num_threads, SOURCE_CMDLINE },
{ 'b', 2, "stream", &stream_wal, SOURCE_CMDLINE },
{ 'b', 3, "progress", &progress, SOURCE_CMDLINE },
{ 's', 'i', "backup-id", &backup_id_string, SOURCE_CMDLINE },
{ 'u', 'j', "threads", &num_threads, SOURCE_CMD_STRICT },
{ 'b', 131, "stream", &stream_wal, SOURCE_CMD_STRICT },
{ 'b', 132, "progress", &progress, SOURCE_CMD_STRICT },
{ 's', 'i', "backup-id", &backup_id_string, SOURCE_CMD_STRICT },
/* backup options */
{ 'b', 10, "backup-pg-log", &backup_logs, SOURCE_CMDLINE },
{ 'f', 'b', "backup-mode", opt_backup_mode, SOURCE_CMDLINE },
{ 'b', 'C', "smooth-checkpoint", &smooth_checkpoint, SOURCE_CMDLINE },
{ 's', 'S', "slot", &replication_slot, SOURCE_CMDLINE },
{ 'u', 11, "archive-timeout", &archive_timeout, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S },
{ 'b', 12, "delete-wal", &delete_wal, SOURCE_CMDLINE },
{ 'b', 13, "delete-expired", &delete_expired, SOURCE_CMDLINE },
{ 's', 14, "master-db", &master_db, SOURCE_CMDLINE, },
{ 's', 15, "master-host", &master_host, SOURCE_CMDLINE, },
{ 's', 16, "master-port", &master_port, SOURCE_CMDLINE, },
{ 's', 17, "master-user", &master_user, SOURCE_CMDLINE, },
{ 'u', 18, "replica-timeout", &replica_timeout, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S },
{ 'b', 133, "backup-pg-log", &backup_logs, SOURCE_CMD_STRICT },
{ 'f', 'b', "backup-mode", opt_backup_mode, SOURCE_CMD_STRICT },
{ 'b', 'C', "smooth-checkpoint", &smooth_checkpoint, SOURCE_CMD_STRICT },
{ 's', 'S', "slot", &replication_slot, SOURCE_CMD_STRICT },
{ 'b', 134, "delete-wal", &delete_wal, SOURCE_CMD_STRICT },
{ 'b', 135, "delete-expired", &delete_expired, SOURCE_CMD_STRICT },
/* TODO not completed feature. Make it unavailiable from user level
{ 'b', 18, "remote", &is_remote_backup, SOURCE_CMDLINE, }, */
{ 'b', 18, "remote", &is_remote_backup, SOURCE_CMD_STRICT, }, */
/* restore options */
{ 's', 20, "time", &target_time, SOURCE_CMDLINE },
{ 's', 21, "xid", &target_xid, SOURCE_CMDLINE },
{ 's', 22, "inclusive", &target_inclusive, SOURCE_CMDLINE },
{ 'u', 23, "timeline", &target_tli, SOURCE_CMDLINE },
{ 'f', 'T', "tablespace-mapping", opt_tablespace_map, SOURCE_CMDLINE },
{ 'b', 24, "immediate", &target_immediate, SOURCE_CMDLINE },
{ 's', 25, "recovery-target-name", &target_name, SOURCE_CMDLINE },
{ 's', 26, "recovery-target-action", &target_action, SOURCE_CMDLINE },
{ 'b', 'R', "restore-as-replica", &restore_as_replica, SOURCE_CMDLINE },
{ 'b', 27, "no-validate", &restore_no_validate, SOURCE_CMDLINE },
{ 's', 28, "lsn", &target_lsn, SOURCE_CMDLINE },
{ 'b', 29, "skip-block-validation", &skip_block_validation, SOURCE_CMDLINE },
{ 's', 136, "time", &target_time, SOURCE_CMD_STRICT },
{ 's', 137, "xid", &target_xid, SOURCE_CMD_STRICT },
{ 's', 138, "inclusive", &target_inclusive, SOURCE_CMD_STRICT },
{ 'u', 139, "timeline", &target_tli, SOURCE_CMD_STRICT },
{ 'f', 'T', "tablespace-mapping", opt_tablespace_map, SOURCE_CMD_STRICT },
{ 'b', 140, "immediate", &target_immediate, SOURCE_CMD_STRICT },
{ 's', 141, "recovery-target-name", &target_name, SOURCE_CMD_STRICT },
{ 's', 142, "recovery-target-action", &target_action, SOURCE_CMD_STRICT },
{ 'b', 'R', "restore-as-replica", &restore_as_replica, SOURCE_CMD_STRICT },
{ 'b', 143, "no-validate", &restore_no_validate, SOURCE_CMD_STRICT },
{ 's', 144, "lsn", &target_lsn, SOURCE_CMD_STRICT },
{ 'b', 154, "skip-block-validation", &skip_block_validation, SOURCE_CMD_STRICT },
/* delete options */
{ 'b', 130, "wal", &delete_wal, SOURCE_CMDLINE },
{ 'b', 131, "expired", &delete_expired, SOURCE_CMDLINE },
{ 'b', 132, "all", &apply_to_all, SOURCE_CMDLINE },
{ 'b', 145, "wal", &delete_wal, SOURCE_CMD_STRICT },
{ 'b', 146, "expired", &delete_expired, SOURCE_CMD_STRICT },
/* TODO not implemented yet */
{ 'b', 133, "force", &force_delete, SOURCE_CMDLINE },
/* retention options */
{ 'u', 134, "retention-redundancy", &retention_redundancy, SOURCE_CMDLINE },
{ 'u', 135, "retention-window", &retention_window, SOURCE_CMDLINE },
{ 'b', 147, "force", &force_delete, SOURCE_CMD_STRICT },
/* compression options */
{ 'f', 136, "compress-algorithm", opt_compress_alg, SOURCE_CMDLINE },
{ 'u', 137, "compress-level", &compress_level, SOURCE_CMDLINE },
{ 'b', 138, "compress", &compress_shortcut, SOURCE_CMDLINE },
/* logging options */
{ 'f', 140, "log-level-console", opt_log_level_console, SOURCE_CMDLINE },
{ 'f', 141, "log-level-file", opt_log_level_file, SOURCE_CMDLINE },
{ 's', 142, "log-filename", &log_filename, SOURCE_CMDLINE },
{ 's', 143, "error-log-filename", &error_log_filename, SOURCE_CMDLINE },
{ 's', 144, "log-directory", &log_directory, SOURCE_CMDLINE },
{ 'U', 145, "log-rotation-size", &log_rotation_size, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_KB },
{ 'U', 146, "log-rotation-age", &log_rotation_age, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_MS },
{ 'b', 148, "compress", &compress_shortcut, SOURCE_CMD_STRICT },
/* connection options */
{ 's', 'd', "pgdatabase", &pgut_dbname, SOURCE_CMDLINE },
{ 's', 'h', "pghost", &host, SOURCE_CMDLINE },
{ 's', 'p', "pgport", &port, SOURCE_CMDLINE },
{ 's', 'U', "pguser", &username, SOURCE_CMDLINE },
{ 'B', 'w', "no-password", &prompt_password, SOURCE_CMDLINE },
{ 'b', 'W', "password", &force_password, SOURCE_CMDLINE },
{ 'B', 'w', "no-password", &prompt_password, SOURCE_CMD_STRICT },
{ 'b', 'W', "password", &force_password, SOURCE_CMD_STRICT },
/* other options */
{ 'U', 150, "system-identifier", &system_identifier, SOURCE_FILE_STRICT },
{ 's', 151, "instance", &instance_name, SOURCE_CMDLINE },
#if PG_VERSION_NUM >= 110000
{ 'u', 152, "xlog-seg-size", &xlog_seg_size, SOURCE_FILE_STRICT},
#endif
{ 's', 149, "instance", &instance_name, SOURCE_CMD_STRICT },
/* archive-push options */
{ 's', 160, "wal-file-path", &wal_file_path, SOURCE_CMDLINE },
{ 's', 161, "wal-file-name", &wal_file_name, SOURCE_CMDLINE },
{ 'b', 162, "overwrite", &file_overwrite, SOURCE_CMDLINE },
{ 's', 150, "wal-file-path", &wal_file_path, SOURCE_CMD_STRICT },
{ 's', 151, "wal-file-name", &wal_file_name, SOURCE_CMD_STRICT },
{ 'b', 152, "overwrite", &file_overwrite, SOURCE_CMD_STRICT },
/* show options */
{ 'f', 170, "format", opt_show_format, SOURCE_CMDLINE },
{ 'f', 153, "format", opt_show_format, SOURCE_CMD_STRICT },
{ 0 }
};
@ -237,9 +182,12 @@ main(int argc, char *argv[])
struct stat stat_buf;
int rc;
/* initialize configuration */
/* Initialize current backup */
pgBackupInit(&current);
/* Initialize current instance configuration */
init_config(&instance_config);
PROGRAM_NAME = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], "pgscripts");
@ -352,8 +300,10 @@ main(int argc, char *argv[])
}
optind += 1;
/* Parse command line arguments */
pgut_getopt(argc, argv, options);
/* Parse command line only arguments */
config_get_opt(argc, argv, cmd_options, instance_options);
pgut_init();
if (help_opt)
help_command(command_name);
@ -424,34 +374,36 @@ main(int argc, char *argv[])
* Read options from env variables or from config file,
* unless we're going to set them via set-config.
*/
if (instance_name && backup_subcmd != SET_CONFIG_CMD)
if (instance_name)
{
char path[MAXPGPATH];
/* Read environment variables */
pgut_getopt_env(options);
config_get_opt_env(instance_options);
/* Read options from configuration file */
join_path_components(path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);
pgut_readopt(path, options, ERROR, true);
config_read_opt(path, instance_options, ERROR, true);
}
/* Initialize logger */
init_logger(backup_path);
init_logger(backup_path, &instance_config.logger);
/*
* We have read pgdata path from command line or from configuration file.
* Ensure that pgdata is an absolute path.
*/
if (pgdata != NULL && !is_absolute_path(pgdata))
if (instance_config.pgdata != NULL &&
!is_absolute_path(instance_config.pgdata))
elog(ERROR, "-D, --pgdata must be an absolute path");
#if PG_VERSION_NUM >= 110000
/* Check xlog-seg-size option */
if (instance_name &&
backup_subcmd != INIT_CMD && backup_subcmd != SHOW_CMD &&
backup_subcmd != ADD_INSTANCE_CMD && !IsValidWalSegSize(xlog_seg_size))
elog(ERROR, "Invalid WAL segment size %u", xlog_seg_size);
backup_subcmd != ADD_INSTANCE_CMD && backup_subcmd != SET_CONFIG_CMD &&
!IsValidWalSegSize(instance_config.xlog_seg_size))
elog(ERROR, "Invalid WAL segment size %u", instance_config.xlog_seg_size);
#endif
/* Sanity check of --backup-id option */
@ -471,12 +423,12 @@ main(int argc, char *argv[])
}
/* Setup stream options. They are used in streamutil.c. */
if (host != NULL)
dbhost = pstrdup(host);
if (port != NULL)
dbport = pstrdup(port);
if (username != NULL)
dbuser = pstrdup(username);
if (instance_config.pghost != NULL)
dbhost = pstrdup(instance_config.pghost);
if (instance_config.pgport != NULL)
dbport = pstrdup(instance_config.pgport);
if (instance_config.pguser != NULL)
dbuser = pstrdup(instance_config.pguser);
/* setup exclusion list for file search */
if (!backup_logs)
@ -559,9 +511,11 @@ main(int argc, char *argv[])
do_merge(current.backup_id);
break;
case SHOW_CONFIG_CMD:
return do_configure(true);
do_show_config();
break;
case SET_CONFIG_CMD:
return do_configure(false);
do_set_config();
break;
case NO_CMD:
/* Should not happen */
elog(ERROR, "Unknown subcommand");
@ -571,25 +525,13 @@ main(int argc, char *argv[])
}
static void
opt_backup_mode(pgut_option *opt, const char *arg)
opt_backup_mode(ConfigOption *opt, const char *arg)
{
current.backup_mode = parse_backup_mode(arg);
}
static void
opt_log_level_console(pgut_option *opt, const char *arg)
{
log_level_console = parse_log_level(arg);
}
static void
opt_log_level_file(pgut_option *opt, const char *arg)
{
log_level_file = parse_log_level(arg);
}
static void
opt_show_format(pgut_option *opt, const char *arg)
opt_show_format(ConfigOption *opt, const char *arg)
{
const char *v = arg;
size_t len;
@ -612,12 +554,6 @@ opt_show_format(pgut_option *opt, const char *arg)
elog(ERROR, "Invalid show format \"%s\"", arg);
}
static void
opt_compress_alg(pgut_option *opt, const char *arg)
{
compress_alg = parse_compress_alg(arg);
}
/*
* Initialize compress and sanity checks for compress.
*/
@ -626,20 +562,20 @@ compress_init(void)
{
/* Default algorithm is zlib */
if (compress_shortcut)
compress_alg = ZLIB_COMPRESS;
instance_config.compress_alg = ZLIB_COMPRESS;
if (backup_subcmd != SET_CONFIG_CMD)
{
if (compress_level != COMPRESS_LEVEL_DEFAULT
&& compress_alg == NOT_DEFINED_COMPRESS)
if (instance_config.compress_level != COMPRESS_LEVEL_DEFAULT
&& instance_config.compress_alg == NOT_DEFINED_COMPRESS)
elog(ERROR, "Cannot specify compress-level option without compress-alg option");
}
if (compress_level < 0 || compress_level > 9)
if (instance_config.compress_level < 0 || instance_config.compress_level > 9)
elog(ERROR, "--compress-level value must be in the range from 0 to 9");
if (compress_level == 0)
compress_alg = NOT_DEFINED_COMPRESS;
if (instance_config.compress_level == 0)
instance_config.compress_alg = NOT_DEFINED_COMPRESS;
if (backup_subcmd == BACKUP_CMD || backup_subcmd == ARCHIVE_PUSH_CMD)
{
@ -648,7 +584,7 @@ compress_init(void)
elog(ERROR, "This build does not support zlib compression");
else
#endif
if (compress_alg == PGLZ_COMPRESS && num_threads > 1)
if (instance_config.compress_alg == PGLZ_COMPRESS && num_threads > 1)
elog(ERROR, "Multithread backup does not support pglz compression");
}
}

View File

@ -24,6 +24,7 @@
#include "port/atomics.h"
#endif
#include "utils/configuration.h"
#include "utils/logger.h"
#include "utils/parray.h"
#include "utils/pgut.h"
@ -158,7 +159,11 @@ typedef enum ShowFormat
#define BYTES_INVALID (-1)
#define BLOCKNUM_INVALID (-1)
typedef struct pgBackupConfig
/*
* An instance configuration. It can be stored in a configuration file or passed
* from command line.
*/
typedef struct InstanceConfig
{
uint64 system_identifier;
uint32 xlog_seg_size;
@ -173,24 +178,24 @@ typedef struct pgBackupConfig
const char *master_port;
const char *master_db;
const char *master_user;
int replica_timeout;
uint32 replica_timeout;
int archive_timeout;
/* Wait timeout for WAL segment archiving */
uint32 archive_timeout;
int log_level_console;
int log_level_file;
char *log_filename;
char *error_log_filename;
char *log_directory;
uint64 log_rotation_size;
uint64 log_rotation_age;
/* Logger parameters */
LoggerConfig logger;
/* Retention options. 0 disables the option. */
uint32 retention_redundancy;
uint32 retention_window;
CompressAlg compress_alg;
int compress_level;
} pgBackupConfig;
} InstanceConfig;
extern ConfigOption instance_options[];
extern InstanceConfig instance_config;
typedef struct pgBackup pgBackup;
@ -331,7 +336,6 @@ typedef struct
/* directory options */
extern char *backup_path;
extern char backup_instance_path[MAXPGPATH];
extern char *pgdata;
extern char arclog_path[MAXPGPATH];
/* common options */
@ -345,15 +349,7 @@ extern char *replication_slot;
/* backup options */
extern bool smooth_checkpoint;
#define ARCHIVE_TIMEOUT_DEFAULT 300
extern uint32 archive_timeout;
extern bool is_remote_backup;
extern const char *master_db;
extern const char *master_host;
extern const char *master_port;
extern const char *master_user;
#define REPLICA_TIMEOUT_DEFAULT 300
extern uint32 replica_timeout;
extern bool is_ptrack_support;
extern bool is_checksum_enabled;
@ -366,25 +362,13 @@ extern bool skip_block_validation;
/* delete options */
extern bool delete_wal;
extern bool delete_expired;
extern bool apply_to_all;
extern bool force_delete;
/* retention options. 0 disables the option */
#define RETENTION_REDUNDANCY_DEFAULT 0
#define RETENTION_WINDOW_DEFAULT 0
extern uint32 retention_redundancy;
extern uint32 retention_window;
/* compression options */
extern CompressAlg compress_alg;
extern int compress_level;
extern bool compress_shortcut;
/* other options */
extern char *instance_name;
extern uint64 system_identifier;
extern uint32 xlog_seg_size;
/* show options */
extern ShowFormat show_format;
@ -435,13 +419,9 @@ extern int do_archive_get(char *wal_file_path, char *wal_file_name);
/* in configure.c */
extern int do_configure(bool show_only);
extern void pgBackupConfigInit(pgBackupConfig *config);
extern void writeBackupCatalogConfig(FILE *out, pgBackupConfig *config);
extern void writeBackupCatalogConfigFile(pgBackupConfig *config);
extern pgBackupConfig* readBackupCatalogConfigFile(void);
extern uint32 get_config_xlog_seg_size(void);
extern void do_show_config(void);
extern void do_set_config(void);
extern void init_config(InstanceConfig *config);
/* in show.c */
extern int do_show(time_t requested_backup_id);
@ -510,7 +490,7 @@ extern void create_data_directories(const char *data_dir,
bool extract_tablespaces);
extern void read_tablespace_map(parray *files, const char *backup_dir);
extern void opt_tablespace_map(pgut_option *opt, const char *arg);
extern void opt_tablespace_map(ConfigOption *opt, const char *arg);
extern void check_tablespace_mapping(pgBackup *backup);
extern void print_file_list(FILE *out, const parray *files, const char *root);

View File

@ -59,12 +59,13 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
if (is_restore)
{
if (pgdata == NULL)
if (instance_config.pgdata == NULL)
elog(ERROR,
"required parameter not specified: PGDATA (-D, --pgdata)");
/* Check if restore destination empty */
if (!dir_is_empty(pgdata))
elog(ERROR, "restore destination is not empty: \"%s\"", pgdata);
if (!dir_is_empty(instance_config.pgdata))
elog(ERROR, "restore destination is not empty: \"%s\"",
instance_config.pgdata);
}
if (instance_name == NULL)
@ -320,7 +321,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
*/
validate_wal(dest_backup, arclog_path, rt->recovery_target_time,
rt->recovery_target_xid, rt->recovery_target_lsn,
base_full_backup->tli, xlog_seg_size);
base_full_backup->tli, instance_config.xlog_seg_size);
}
/* Orphinize every OK descendant of corrupted backup */
else
@ -445,7 +446,7 @@ restore_backup(pgBackup *backup)
* this_backup_path = $BACKUP_PATH/backups/instance_name/backup_id
*/
pgBackupGetPath(backup, this_backup_path, lengthof(this_backup_path), NULL);
create_data_directories(pgdata, this_backup_path, true);
create_data_directories(instance_config.pgdata, this_backup_path, true);
/*
* Get list of files which need to be restored.
@ -497,7 +498,8 @@ restore_backup(pgBackup *backup)
parray_walk(files, pgFileFree);
parray_free(files);
if (log_level_console <= LOG || log_level_file <= LOG)
if (logger_config.log_level_console <= LOG ||
logger_config.log_level_file <= LOG)
elog(LOG, "restore %s backup completed", base36enc(backup->start_time));
}
@ -517,12 +519,12 @@ remove_deleted_files(pgBackup *backup)
pgBackupGetPath(backup, filelist_path, lengthof(filelist_path), DATABASE_FILE_LIST);
/* Read backup's filelist using target database path as base path */
files = dir_read_file_list(pgdata, filelist_path);
files = dir_read_file_list(instance_config.pgdata, filelist_path);
parray_qsort(files, pgFileComparePathDesc);
/* Get list of files actually existing in target database */
files_restored = parray_new();
dir_list_file(files_restored, pgdata, true, true, false);
dir_list_file(files_restored, instance_config.pgdata, true, true, false);
/* To delete from leaf, sort in reversed order */
parray_qsort(files_restored, pgFileComparePathDesc);
@ -534,8 +536,10 @@ remove_deleted_files(pgBackup *backup)
if (parray_bsearch(files, file, pgFileComparePathDesc) == NULL)
{
pgFileDelete(file);
if (log_level_console <= LOG || log_level_file <= LOG)
elog(LOG, "deleted %s", GetRelativePath(file->path, pgdata));
if (logger_config.log_level_console <= LOG ||
logger_config.log_level_file <= LOG)
elog(LOG, "deleted %s", GetRelativePath(file->path,
instance_config.pgdata));
}
}
@ -617,7 +621,7 @@ restore_files(void *arg)
{
char to_path[MAXPGPATH];
join_path_components(to_path, pgdata,
join_path_components(to_path, instance_config.pgdata,
file->path + strlen(from_root) + 1);
restore_data_file(to_path, file,
arguments->backup->backup_mode == BACKUP_MODE_DIFF_DELTA,
@ -625,7 +629,7 @@ restore_files(void *arg)
parse_program_version(arguments->backup->program_version));
}
else
copy_file(from_root, pgdata, file);
copy_file(from_root, instance_config.pgdata, file);
/* print size of restored file */
if (file->write_size != BYTES_INVALID)
@ -660,7 +664,7 @@ create_recovery_conf(time_t backup_id,
elog(LOG, "----------------------------------------");
elog(LOG, "creating recovery.conf");
snprintf(path, lengthof(path), "%s/recovery.conf", pgdata);
snprintf(path, lengthof(path), "%s/recovery.conf", instance_config.pgdata);
fp = fopen(path, "wt");
if (fp == NULL)
elog(ERROR, "cannot open recovery.conf \"%s\": %s", path,

View File

@ -521,8 +521,8 @@ show_instance_json(parray *backup_list)
/* Begin of instance object */
json_add(buf, JT_BEGIN_OBJECT, &json_level);
json_add_value(buf, "instance", instance_name, json_level, false);
json_add_key(buf, "backups", json_level, true);
json_add_value(buf, "instance", instance_name, json_level, true);
json_add_key(buf, "backups", json_level);
/*
* List backups.
@ -542,7 +542,7 @@ show_instance_json(parray *backup_list)
json_add(buf, JT_BEGIN_OBJECT, &json_level);
json_add_value(buf, "id", base36enc(backup->start_time), json_level,
false);
true);
if (backup->parent_backup != 0)
json_add_value(buf, "parent-backup-id",
@ -558,20 +558,20 @@ show_instance_json(parray *backup_list)
deparse_compress_alg(backup->compress_alg), json_level,
true);
json_add_key(buf, "compress-level", json_level, true);
json_add_key(buf, "compress-level", json_level);
appendPQExpBuffer(buf, "%d", backup->compress_level);
json_add_value(buf, "from-replica",
backup->from_replica ? "true" : "false", json_level,
true);
false);
json_add_key(buf, "block-size", json_level, true);
json_add_key(buf, "block-size", json_level);
appendPQExpBuffer(buf, "%u", backup->block_size);
json_add_key(buf, "xlog-block-size", json_level, true);
json_add_key(buf, "xlog-block-size", json_level);
appendPQExpBuffer(buf, "%u", backup->wal_block_size);
json_add_key(buf, "checksum-version", json_level, true);
json_add_key(buf, "checksum-version", json_level);
appendPQExpBuffer(buf, "%u", backup->checksum_version);
json_add_value(buf, "program-version", backup->program_version,
@ -579,10 +579,10 @@ show_instance_json(parray *backup_list)
json_add_value(buf, "server-version", backup->server_version,
json_level, true);
json_add_key(buf, "current-tli", json_level, true);
json_add_key(buf, "current-tli", json_level);
appendPQExpBuffer(buf, "%d", backup->tli);
json_add_key(buf, "parent-tli", json_level, true);
json_add_key(buf, "parent-tli", json_level);
parent_tli = get_parent_tli(backup->tli);
appendPQExpBuffer(buf, "%u", parent_tli);
@ -603,7 +603,7 @@ show_instance_json(parray *backup_list)
json_add_value(buf, "end-time", timestamp, json_level, true);
}
json_add_key(buf, "recovery-xid", json_level, true);
json_add_key(buf, "recovery-xid", json_level);
appendPQExpBuffer(buf, XID_FMT, backup->recovery_xid);
if (backup->recovery_time > 0)
@ -614,13 +614,13 @@ show_instance_json(parray *backup_list)
if (backup->data_bytes != BYTES_INVALID)
{
json_add_key(buf, "data-bytes", json_level, true);
json_add_key(buf, "data-bytes", json_level);
appendPQExpBuffer(buf, INT64_FORMAT, backup->data_bytes);
}
if (backup->wal_bytes != BYTES_INVALID)
{
json_add_key(buf, "wal-bytes", json_level, true);
json_add_key(buf, "wal-bytes", json_level);
appendPQExpBuffer(buf, INT64_FORMAT, backup->wal_bytes);
}

View File

@ -112,7 +112,8 @@ get_current_timeline(bool safe)
size_t size;
/* First fetch file... */
buffer = slurpFile(pgdata, "global/pg_control", &size, safe);
buffer = slurpFile(instance_config.pgdata, "global/pg_control", &size,
safe);
if (safe && buffer == NULL)
return 0;
@ -241,7 +242,8 @@ get_data_checksum_version(bool safe)
size_t size;
/* First fetch file... */
buffer = slurpFile(pgdata, "global/pg_control", &size, safe);
buffer = slurpFile(instance_config.pgdata, "global/pg_control", &size,
safe);
if (buffer == NULL)
return 0;
digestControlFile(&ControlFile, buffer, size);
@ -250,36 +252,6 @@ get_data_checksum_version(bool safe)
return ControlFile.data_checksum_version;
}
/*
* Convert time_t value to ISO-8601 format string. Always set timezone offset.
*/
void
time2iso(char *buf, size_t len, time_t time)
{
struct tm *ptm = gmtime(&time);
time_t gmt = mktime(ptm);
time_t offset;
char *ptr = buf;
ptm = localtime(&time);
offset = time - gmt + (ptm->tm_isdst ? 3600 : 0);
strftime(ptr, len, "%Y-%m-%d %H:%M:%S", ptm);
ptr += strlen(ptr);
snprintf(ptr, len - (ptr - buf), "%c%02d",
(offset >= 0) ? '+' : '-',
abs((int) offset) / SECS_PER_HOUR);
if (abs((int) offset) % SECS_PER_HOUR != 0)
{
ptr += strlen(ptr);
snprintf(ptr, len - (ptr - buf), ":%02d",
abs((int) offset % SECS_PER_HOUR) / SECS_PER_MINUTE);
}
}
/*
* Parse string representation of the server version.
*/

1499
src/utils/configuration.c Normal file

File diff suppressed because it is too large Load Diff

106
src/utils/configuration.h Normal file
View File

@ -0,0 +1,106 @@
/*-------------------------------------------------------------------------
*
* configuration.h: - prototypes of functions and structures for
* configuration.
*
* Copyright (c) 2018, Postgres Professional
*
*-------------------------------------------------------------------------
*/
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#include "postgres_fe.h"
#include "access/xlogdefs.h"
#define INFINITE_STR "INFINITE"
typedef enum OptionSource
{
SOURCE_DEFAULT,
SOURCE_FILE_STRICT,
SOURCE_CMD_STRICT,
SOURCE_ENV,
SOURCE_FILE,
SOURCE_CMD,
SOURCE_CONST
} OptionSource;
typedef struct ConfigOption ConfigOption;
typedef void (*option_assign_fn) (ConfigOption *opt, const char *arg);
/* Returns allocated string value */
typedef char *(*option_get_fn) (ConfigOption *opt);
/*
* type:
* b: bool (true)
* B: bool (false)
* f: option_fn
* i: 32bit signed integer
* u: 32bit unsigned integer
* I: 64bit signed integer
* U: 64bit unsigned integer
* s: string
* t: time_t
*/
struct ConfigOption
{
char type;
uint8 sname; /* short name */
const char *lname; /* long name */
void *var; /* pointer to variable */
OptionSource allowed; /* allowed source */
OptionSource source; /* actual source */
const char *group; /* option group name */
int flags; /* option unit */
option_get_fn get_value; /* function to get the value as a string,
should return allocated string*/
};
/*
* bit values in "flags" of an option
*/
#define OPTION_UNIT_KB 0x1000 /* value is in kilobytes */
#define OPTION_UNIT_BLOCKS 0x2000 /* value is in blocks */
#define OPTION_UNIT_XBLOCKS 0x3000 /* value is in xlog blocks */
#define OPTION_UNIT_XSEGS 0x4000 /* value is in xlog segments */
#define OPTION_UNIT_MEMORY 0xF000 /* mask for size-related units */
#define OPTION_UNIT_MS 0x10000 /* value is in milliseconds */
#define OPTION_UNIT_S 0x20000 /* value is in seconds */
#define OPTION_UNIT_MIN 0x30000 /* value is in minutes */
#define OPTION_UNIT_TIME 0xF0000 /* mask for time-related units */
#define OPTION_UNIT (OPTION_UNIT_MEMORY | OPTION_UNIT_TIME)
extern int config_get_opt(int argc, char **argv, ConfigOption cmd_options[],
ConfigOption options[]);
extern int config_read_opt(const char *path, ConfigOption options[], int elevel,
bool strict);
extern void config_get_opt_env(ConfigOption options[]);
extern void config_set_opt(ConfigOption options[], void *var,
OptionSource source);
extern char *option_get_value(ConfigOption *opt);
extern bool parse_bool(const char *value, bool *result);
extern bool parse_bool_with_len(const char *value, size_t len, bool *result);
extern bool parse_int32(const char *value, int32 *result, int flags);
extern bool parse_uint32(const char *value, uint32 *result, int flags);
extern bool parse_int64(const char *value, int64 *result, int flags);
extern bool parse_uint64(const char *value, uint64 *result, int flags);
extern bool parse_time(const char *value, time_t *result, bool utc_default);
extern bool parse_int(const char *value, int *result, int flags,
const char **hintmsg);
extern bool parse_lsn(const char *value, XLogRecPtr *result);
extern void time2iso(char *buf, size_t len, time_t time);
extern void convert_from_base_unit(int64 base_value, int base_unit,
int64 *value, const char **unit);
extern void convert_from_base_unit_u(uint64 base_value, int base_unit,
uint64 *value, const char **unit);
#endif /* CONFIGURATION_H */

View File

@ -12,6 +12,8 @@
static void json_add_indent(PQExpBuffer buf, int32 level);
static void json_add_escaped(PQExpBuffer buf, const char *str);
static bool add_comma = false;
/*
* Start or end json token. Currently it is a json object or array.
*
@ -25,6 +27,7 @@ json_add(PQExpBuffer buf, JsonToken type, int32 *level)
case JT_BEGIN_ARRAY:
appendPQExpBufferChar(buf, '[');
*level += 1;
add_comma = false;
break;
case JT_END_ARRAY:
*level -= 1;
@ -33,11 +36,13 @@ json_add(PQExpBuffer buf, JsonToken type, int32 *level)
else
json_add_indent(buf, *level);
appendPQExpBufferChar(buf, ']');
add_comma = true;
break;
case JT_BEGIN_OBJECT:
json_add_indent(buf, *level);
appendPQExpBufferChar(buf, '{');
*level += 1;
add_comma = false;
break;
case JT_END_OBJECT:
*level -= 1;
@ -46,6 +51,7 @@ json_add(PQExpBuffer buf, JsonToken type, int32 *level)
else
json_add_indent(buf, *level);
appendPQExpBufferChar(buf, '}');
add_comma = true;
break;
default:
break;
@ -56,7 +62,7 @@ json_add(PQExpBuffer buf, JsonToken type, int32 *level)
* Add json object's key. If it isn't first key we need to add a comma.
*/
void
json_add_key(PQExpBuffer buf, const char *name, int32 level, bool add_comma)
json_add_key(PQExpBuffer buf, const char *name, int32 level)
{
if (add_comma)
appendPQExpBufferChar(buf, ',');
@ -64,6 +70,8 @@ json_add_key(PQExpBuffer buf, const char *name, int32 level, bool add_comma)
json_add_escaped(buf, name);
appendPQExpBufferStr(buf, ": ");
add_comma = true;
}
/*
@ -72,10 +80,14 @@ json_add_key(PQExpBuffer buf, const char *name, int32 level, bool add_comma)
*/
void
json_add_value(PQExpBuffer buf, const char *name, const char *value,
int32 level, bool add_comma)
int32 level, bool escaped)
{
json_add_key(buf, name, level, add_comma);
json_add_escaped(buf, value);
json_add_key(buf, name, level);
if (escaped)
json_add_escaped(buf, value);
else
appendPQExpBufferStr(buf, value);
}
static void

View File

@ -25,9 +25,8 @@ typedef enum
} JsonToken;
extern void json_add(PQExpBuffer buf, JsonToken type, int32 *level);
extern void json_add_key(PQExpBuffer buf, const char *name, int32 level,
bool add_comma);
extern void json_add_key(PQExpBuffer buf, const char *name, int32 level);
extern void json_add_value(PQExpBuffer buf, const char *name, const char *value,
int32 level, bool add_comma);
int32 level, bool escaped);
#endif /* PROBACKUP_JSON_H */

View File

@ -15,24 +15,17 @@
#include "pgut.h"
#include "thread.h"
#include "utils/configuration.h"
/* Logger parameters */
int log_level_console = LOG_LEVEL_CONSOLE_DEFAULT;
int log_level_file = LOG_LEVEL_FILE_DEFAULT;
char *log_filename = NULL;
char *error_log_filename = NULL;
char *log_directory = NULL;
/*
* If log_path is empty logging is not initialized.
* We will log only into stderr
*/
char log_path[MAXPGPATH] = "";
/* Maximum size of an individual log file in kilobytes */
uint64 log_rotation_size = 0;
/* Maximum lifetime of an individual log file in minutes */
uint64 log_rotation_age = 0;
LoggerConfig logger_config = {
LOG_LEVEL_CONSOLE_DEFAULT,
LOG_LEVEL_FILE_DEFAULT,
LOG_FILENAME_DEFAULT,
NULL,
LOG_ROTATION_SIZE_DEFAULT,
LOG_ROTATION_AGE_DEFAULT
};
/* Implementation for logging.h */
@ -68,17 +61,24 @@ static bool loggin_in_progress = false;
static pthread_mutex_t log_file_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Initialize logger.
*
* If log_directory wasn't set by a user we use full path:
* backup_directory/log
*/
void
init_logger(const char *root_path)
init_logger(const char *root_path, LoggerConfig *config)
{
/* Set log path */
if (log_level_file != LOG_OFF || error_log_filename)
if (config->log_directory == NULL)
{
if (log_directory)
strcpy(log_path, log_directory);
else
join_path_components(log_path, root_path, LOG_DIRECTORY_DEFAULT);
config->log_directory = palloc(MAXPGPATH);
join_path_components(config->log_directory,
root_path, LOG_DIRECTORY_DEFAULT);
}
logger_config = *config;
}
static void
@ -157,10 +157,11 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
time_t log_time = (time_t) time(NULL);
char strfbuf[128];
write_to_file = elevel >= log_level_file && log_path[0] != '\0';
write_to_error_log = elevel >= ERROR && error_log_filename &&
log_path[0] != '\0';
write_to_stderr = elevel >= log_level_console && !file_only;
write_to_file = elevel >= logger_config.log_level_file &&
logger_config.log_directory && logger_config.log_directory[0] != '\0';
write_to_error_log = elevel >= ERROR && logger_config.error_log_filename &&
logger_config.log_directory && logger_config.log_directory[0] != '\0';
write_to_stderr = elevel >= logger_config.log_level_console && !file_only;
pthread_lock(&log_file_mutex);
#ifdef WIN32
@ -192,10 +193,10 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
{
if (log_file == NULL)
{
if (log_filename == NULL)
if (logger_config.log_filename == NULL)
open_logfile(&log_file, LOG_FILENAME_DEFAULT);
else
open_logfile(&log_file, log_filename);
open_logfile(&log_file, logger_config.log_filename);
}
fprintf(log_file, "%s: ", strfbuf);
@ -214,7 +215,7 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
if (write_to_error_log)
{
if (error_log_file == NULL)
open_logfile(&error_log_file, error_log_filename);
open_logfile(&error_log_file, logger_config.error_log_filename);
fprintf(error_log_file, "%s: ", strfbuf);
write_elevel(error_log_file, elevel);
@ -263,7 +264,7 @@ elog_stderr(int elevel, const char *fmt, ...)
* Do not log message if severity level is less than log_level.
* It is the little optimisation to put it here not in elog_internal().
*/
if (elevel < log_level_console && elevel < ERROR)
if (elevel < logger_config.log_level_console && elevel < ERROR)
return;
va_start(args, fmt);
@ -290,7 +291,8 @@ elog(int elevel, const char *fmt, ...)
* Do not log message if severity level is less than log_level.
* It is the little optimisation to put it here not in elog_internal().
*/
if (elevel < log_level_console && elevel < log_level_file && elevel < ERROR)
if (elevel < logger_config.log_level_console &&
elevel < logger_config.log_level_file && elevel < ERROR)
return;
va_start(args, fmt);
@ -310,7 +312,7 @@ elog_file(int elevel, const char *fmt, ...)
* Do not log message if severity level is less than log_level.
* It is the little optimisation to put it here not in elog_internal().
*/
if (elevel < log_level_file && elevel < ERROR)
if (elevel < logger_config.log_level_file && elevel < ERROR)
return;
va_start(args, fmt);
@ -351,7 +353,8 @@ pg_log(eLogType type, const char *fmt, ...)
* Do not log message if severity level is less than log_level.
* It is the little optimisation to put it here not in elog_internal().
*/
if (elevel < log_level_console && elevel < log_level_file && elevel < ERROR)
if (elevel < logger_config.log_level_console &&
elevel < logger_config.log_level_file && elevel < ERROR)
return;
va_start(args, fmt);
@ -437,12 +440,13 @@ logfile_getname(const char *format, time_t timestamp)
size_t len;
struct tm *tm = localtime(&timestamp);
if (log_path[0] == '\0')
if (logger_config.log_directory == NULL ||
logger_config.log_directory[0] == '\0')
elog_stderr(ERROR, "logging path is not set");
filename = (char *) palloc(MAXPGPATH);
snprintf(filename, MAXPGPATH, "%s/", log_path);
snprintf(filename, MAXPGPATH, "%s/", logger_config.log_directory);
len = strlen(filename);
@ -464,7 +468,7 @@ logfile_open(const char *filename, const char *mode)
/*
* Create log directory if not present; ignore errors
*/
mkdir(log_path, S_IRWXU);
mkdir(logger_config.log_directory, S_IRWXU);
fh = fopen(filename, mode);
@ -498,7 +502,7 @@ open_logfile(FILE **file, const char *filename_format)
filename = logfile_getname(filename_format, cur_time);
/* "log_path" was checked in logfile_getname() */
/* "log_directory" was checked in logfile_getname() */
snprintf(control, MAXPGPATH, "%s.rotation", filename);
if (stat(filename, &st) == -1)
@ -516,10 +520,11 @@ open_logfile(FILE **file, const char *filename_format)
logfile_exists = true;
/* First check for rotation */
if (log_rotation_size > 0 || log_rotation_age > 0)
if (logger_config.log_rotation_size > 0 ||
logger_config.log_rotation_age > 0)
{
/* Check for rotation by age */
if (log_rotation_age > 0)
if (logger_config.log_rotation_age > 0)
{
struct stat control_st;
@ -550,7 +555,7 @@ open_logfile(FILE **file, const char *filename_format)
rotation_requested = (cur_time - creation_time) >
/* convert to seconds from milliseconds */
log_rotation_age / 1000;
logger_config.log_rotation_age / 1000;
}
else
elog_stderr(ERROR, "cannot read creation timestamp from "
@ -561,10 +566,10 @@ open_logfile(FILE **file, const char *filename_format)
}
/* Check for rotation by size */
if (!rotation_requested && log_rotation_size > 0)
if (!rotation_requested && logger_config.log_rotation_size > 0)
rotation_requested = st.st_size >=
/* convert to bytes */
log_rotation_size * 1024L;
logger_config.log_rotation_size * 1024L;
}
logfile_open:

View File

@ -21,33 +21,36 @@
#define ERROR 1
#define LOG_OFF 10
typedef struct LoggerConfig
{
int log_level_console;
int log_level_file;
char *log_filename;
char *error_log_filename;
char *log_directory;
/* Maximum size of an individual log file in kilobytes */
uint64 log_rotation_size;
/* Maximum lifetime of an individual log file in minutes */
uint64 log_rotation_age;
} LoggerConfig;
/* Logger parameters */
extern LoggerConfig logger_config;
extern int log_to_file;
extern int log_level_console;
extern int log_level_file;
#define LOG_ROTATION_SIZE_DEFAULT 0
#define LOG_ROTATION_AGE_DEFAULT 0
extern char *log_filename;
extern char *error_log_filename;
extern char *log_directory;
extern char log_path[MAXPGPATH];
#define LOG_LEVEL_CONSOLE_DEFAULT INFO
#define LOG_LEVEL_FILE_DEFAULT LOG_OFF
#define LOG_ROTATION_SIZE_DEFAULT 0
#define LOG_ROTATION_AGE_DEFAULT 0
extern uint64 log_rotation_size;
extern uint64 log_rotation_age;
#define LOG_LEVEL_CONSOLE_DEFAULT INFO
#define LOG_LEVEL_FILE_DEFAULT LOG_OFF
#define LOG_FILENAME_DEFAULT "pg_probackup.log"
#define LOG_DIRECTORY_DEFAULT "log"
#define LOG_FILENAME_DEFAULT "pg_probackup.log"
#define LOG_DIRECTORY_DEFAULT "log"
#undef elog
extern void elog(int elevel, const char *fmt, ...) pg_attribute_printf(2, 3);
extern void elog_file(int elevel, const char *fmt, ...) pg_attribute_printf(2, 3);
extern void init_logger(const char *root_path);
extern void init_logger(const char *root_path, LoggerConfig *config);
extern int parse_log_level(const char *level);
extern const char *deparse_log_level(int level);

File diff suppressed because it is too large Load Diff

View File

@ -12,63 +12,10 @@
#define PGUT_H
#include "postgres_fe.h"
#include "access/xlogdefs.h"
#include "libpq-fe.h"
#define INFINITE_STR "INFINITE"
typedef enum pgut_optsrc
{
SOURCE_DEFAULT,
SOURCE_FILE_STRICT,
SOURCE_ENV,
SOURCE_FILE,
SOURCE_CMDLINE,
SOURCE_CONST
} pgut_optsrc;
/*
* type:
* b: bool (true)
* B: bool (false)
* f: pgut_optfn
* i: 32bit signed integer
* u: 32bit unsigned integer
* I: 64bit signed integer
* U: 64bit unsigned integer
* s: string
* t: time_t
*/
typedef struct pgut_option
{
char type;
uint8 sname; /* short name */
const char *lname; /* long name */
void *var; /* pointer to variable */
pgut_optsrc allowed; /* allowed source */
pgut_optsrc source; /* actual source */
int flags; /* option unit */
} pgut_option;
typedef void (*pgut_optfn) (pgut_option *opt, const char *arg);
typedef void (*pgut_atexit_callback)(bool fatal, void *userdata);
/*
* bit values in "flags" of an option
*/
#define OPTION_UNIT_KB 0x1000 /* value is in kilobytes */
#define OPTION_UNIT_BLOCKS 0x2000 /* value is in blocks */
#define OPTION_UNIT_XBLOCKS 0x3000 /* value is in xlog blocks */
#define OPTION_UNIT_XSEGS 0x4000 /* value is in xlog segments */
#define OPTION_UNIT_MEMORY 0xF000 /* mask for size-related units */
#define OPTION_UNIT_MS 0x10000 /* value is in milliseconds */
#define OPTION_UNIT_S 0x20000 /* value is in seconds */
#define OPTION_UNIT_MIN 0x30000 /* value is in minutes */
#define OPTION_UNIT_TIME 0xF0000 /* mask for time-related units */
#define OPTION_UNIT (OPTION_UNIT_MEMORY | OPTION_UNIT_TIME)
/*
* pgut client variables and functions
*/
@ -82,10 +29,6 @@ extern void pgut_help(bool details);
/*
* pgut framework variables and functions
*/
extern const char *pgut_dbname;
extern const char *host;
extern const char *port;
extern const char *username;
extern bool prompt_password;
extern bool force_password;
@ -93,23 +36,21 @@ extern bool interrupted;
extern bool in_cleanup;
extern bool in_password; /* User prompts password */
extern int pgut_getopt(int argc, char **argv, pgut_option options[]);
extern int pgut_readopt(const char *path, pgut_option options[], int elevel,
bool strict);
extern void pgut_getopt_env(pgut_option options[]);
extern void pgut_atexit_push(pgut_atexit_callback callback, void *userdata);
extern void pgut_atexit_pop(pgut_atexit_callback callback, void *userdata);
extern void pgut_init(void);
extern void exit_or_abort(int exitcode);
/*
* Database connections
*/
extern char *pgut_get_conninfo_string(PGconn *conn);
extern PGconn *pgut_connect(const char *dbname);
extern PGconn *pgut_connect_extended(const char *pghost, const char *pgport,
const char *dbname, const char *login);
extern PGconn *pgut_connect_replication(const char *dbname);
extern PGconn *pgut_connect_replication_extended(const char *pghost, const char *pgport,
const char *dbname, const char *pguser);
extern PGconn *pgut_connect(const char *host, const char *port,
const char *dbname, const char *username);
extern PGconn *pgut_connect_replication(const char *host, const char *port,
const char *dbname,
const char *username);
extern void pgut_disconnect(PGconn *conn);
extern PGresult *pgut_execute(PGconn* conn, const char *query, int nParams,
const char **params);
@ -154,22 +95,6 @@ extern FILE *pgut_fopen(const char *path, const char *mode, bool missing_ok);
#define AssertMacro(x) ((void) 0)
#endif
extern bool parse_bool(const char *value, bool *result);
extern bool parse_bool_with_len(const char *value, size_t len, bool *result);
extern bool parse_int32(const char *value, int32 *result, int flags);
extern bool parse_uint32(const char *value, uint32 *result, int flags);
extern bool parse_int64(const char *value, int64 *result, int flags);
extern bool parse_uint64(const char *value, uint64 *result, int flags);
extern bool parse_time(const char *value, time_t *result, bool utc_default);
extern bool parse_int(const char *value, int *result, int flags,
const char **hintmsg);
extern bool parse_lsn(const char *value, XLogRecPtr *result);
extern void convert_from_base_unit(int64 base_value, int base_unit,
int64 *value, const char **unit);
extern void convert_from_base_unit_u(uint64 base_value, int base_unit,
uint64 *value, const char **unit);
#define IsSpace(c) (isspace((unsigned char)(c)))
#define IsAlpha(c) (isalpha((unsigned char)(c)))
#define IsAlnum(c) (isalnum((unsigned char)(c)))

View File

@ -275,6 +275,7 @@ do_validate_all(void)
errno = 0;
while ((dent = readdir(dir)))
{
char conf_path[MAXPGPATH];
char child[MAXPGPATH];
struct stat st;
@ -291,10 +292,16 @@ do_validate_all(void)
if (!S_ISDIR(st.st_mode))
continue;
/*
* Initialize instance configuration.
*/
instance_name = dent->d_name;
sprintf(backup_instance_path, "%s/%s/%s", backup_path, BACKUPS_DIR, instance_name);
sprintf(backup_instance_path, "%s/%s/%s",
backup_path, BACKUPS_DIR, instance_name);
sprintf(arclog_path, "%s/%s/%s", backup_path, "wal", instance_name);
xlog_seg_size = get_config_xlog_seg_size();
join_path_components(conf_path, backup_instance_path,
BACKUP_CATALOG_CONF_FILE);
config_read_opt(conf_path, instance_options, ERROR, false);
do_validate_instance();
}
@ -418,7 +425,8 @@ do_validate_instance(void)
/* Validate corresponding WAL files */
if (current_backup->status == BACKUP_STATUS_OK)
validate_wal(current_backup, arclog_path, 0,
0, 0, base_full_backup->tli, xlog_seg_size);
0, 0, base_full_backup->tli,
instance_config.xlog_seg_size);
/*
* Mark every descendant of corrupted backup as orphan
@ -506,7 +514,7 @@ do_validate_instance(void)
/* Revalidation successful, validate corresponding WAL files */
validate_wal(backup, arclog_path, 0,
0, 0, current_backup->tli,
xlog_seg_size);
instance_config.xlog_seg_size);
}
}