mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-02-08 14:28:36 +02:00
- Fix possible broken backup which is getting from standby.
Use --standby-host and --standby-port, if backup is getting from standby. - Add --hard-copy restore option. The option can be used to copy archive WAL to archive directory instead of symlink. git-svn-id: http://pg-rman.googlecode.com/svn/trunk@77 182aca00-e38e-11de-a668-6fd11605f5ce
This commit is contained in:
parent
40fb3560e5
commit
0144cc4fd9
@ -1,5 +1,5 @@
|
||||
# SPEC file for pg_rman
|
||||
# Copyright(C) 2009-2010 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Copyright(C) 2009-2013 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
|
||||
%define _pgdir /usr/pgsql-9.0
|
||||
%define _bindir %{_pgdir}/bin
|
||||
@ -9,7 +9,7 @@
|
||||
## Set general information for pg_rman.
|
||||
Summary: Backup and Recovery Tool for PostgreSQL
|
||||
Name: pg_rman
|
||||
Version: 1.2.5
|
||||
Version: 1.2.6
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Group: Applications/Databases
|
||||
@ -58,7 +58,8 @@ rm -rf %{buildroot}
|
||||
|
||||
# History of pg_rman.
|
||||
%changelog
|
||||
* Mon Sep 2 2013 - NTT OSS Center <otsuka.kenji@lab.ntt.co.jp> 1.2.6-1
|
||||
- Update to 1.2.6
|
||||
* Wed Nov 10 2010 - NTT OSS Center <tomonari.katsumata@oss.ntt.co.jp> 1.2.0-1
|
||||
* Wed Dec 9 2009 - NTT OSS Center <itagaki.takahiro@oss.ntt.co.jp> 1.1.1-1
|
||||
- Initial cut for 1.1.1
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# SPEC file for pg_rman
|
||||
# Copyright(C) 2009-2011 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Copyright(C) 2009-2013 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
|
||||
%define _pgdir /usr/pgsql-9.1
|
||||
%define _bindir %{_pgdir}/bin
|
||||
@ -9,7 +9,7 @@
|
||||
## Set general information for pg_rman.
|
||||
Summary: Backup and Recovery Tool for PostgreSQL
|
||||
Name: pg_rman
|
||||
Version: 1.2.5
|
||||
Version: 1.2.6
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Group: Applications/Databases
|
||||
@ -58,7 +58,8 @@ rm -rf %{buildroot}
|
||||
|
||||
# History of pg_rman.
|
||||
%changelog
|
||||
* Mon Sep 2 2013 - NTT OSS Center <otsuka.kenji@lab.ntt.co.jp> 1.2.6-1
|
||||
- Update to 1.2.6
|
||||
* Wed Nov 10 2010 - NTT OSS Center <tomonari.katsumata@oss.ntt.co.jp> 1.2.0-1
|
||||
* Wed Dec 9 2009 - NTT OSS Center <itagaki.takahiro@oss.ntt.co.jp> 1.1.1-1
|
||||
- Initial cut for 1.1.1
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# SPEC file for pg_rman
|
||||
# Copyright(C) 2009-2012 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
# Copyright(C) 2009-2013 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
|
||||
%define _pgdir /usr/pgsql-9.2
|
||||
%define _bindir %{_pgdir}/bin
|
||||
@ -9,7 +9,7 @@
|
||||
## Set general information for pg_rman.
|
||||
Summary: Backup and Recovery Tool for PostgreSQL
|
||||
Name: pg_rman
|
||||
Version: 1.2.5
|
||||
Version: 1.2.6
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Group: Applications/Databases
|
||||
@ -58,7 +58,8 @@ rm -rf %{buildroot}
|
||||
|
||||
# History of pg_rman.
|
||||
%changelog
|
||||
* Mon Sep 2 2013 - NTT OSS Center <otsuka.kenji@lab.ntt.co.jp> 1.2.6-1
|
||||
- Update to 1.2.6
|
||||
* Wed Nov 10 2010 - NTT OSS Center <tomonari.katsumata@oss.ntt.co.jp> 1.2.0-1
|
||||
* Wed Dec 9 2009 - NTT OSS Center <itagaki.takahiro@oss.ntt.co.jp> 1.1.1-1
|
||||
- Initial cut for 1.1.1
|
||||
|
||||
|
170
backup.c
170
backup.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* backup.c: backup DB cluster, archived WAL, serverlog.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -33,20 +33,22 @@ static void delete_old_files(const char *root, parray *files, int keep_files,
|
||||
int keep_days, int server_version, bool is_arclog);
|
||||
static void backup_files(const char *from_root, const char *to_root,
|
||||
parray *files, parray *prev_files, const XLogRecPtr *lsn, bool compress, const char *prefix);
|
||||
static parray *do_backup_database(parray *backup_list, bool smooth_checkpoint);
|
||||
static parray *do_backup_database(parray *backup_list, pgBackupOption bkupopt);
|
||||
static parray *do_backup_arclog(parray *backup_list);
|
||||
static parray *do_backup_srvlog(parray *backup_list);
|
||||
static void remove_stopinfo_from_backup_label(char *history_file, char *bkup_label);
|
||||
static void make_backup_label(parray *backup_list);
|
||||
static void confirm_block_size(const char *name, int blcksz);
|
||||
static void pg_start_backup(const char *label, bool smooth, pgBackup *backup);
|
||||
static void pg_stop_backup(pgBackup *backup);
|
||||
static void pg_switch_xlog(pgBackup *backup);
|
||||
static void get_lsn(PGresult *res, TimeLineID *timeline, XLogRecPtr *lsn);
|
||||
static void get_xid(PGresult *res, uint32 *xid);
|
||||
static bool execute_restartpoint(pgBackupOption bkupopt);
|
||||
|
||||
static void delete_arclog_link(void);
|
||||
static void delete_online_wal_backup(void);
|
||||
|
||||
static bool fileExists(const char *path);
|
||||
static bool dirExists(const char *path);
|
||||
|
||||
static void execute_freeze(void);
|
||||
@ -65,7 +67,7 @@ static void create_file_list(parray *files, const char *root, const char *prefix
|
||||
* Take a backup of database.
|
||||
*/
|
||||
static parray *
|
||||
do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
do_backup_database(parray *backup_list, pgBackupOption bkupopt)
|
||||
{
|
||||
int i;
|
||||
parray *files; /* backup file list from non-snapshot */
|
||||
@ -75,6 +77,11 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
char label[1024];
|
||||
XLogRecPtr *lsn = NULL;
|
||||
char prev_file_txt[MAXPGPATH]; /* path of the previous backup list file */
|
||||
bool has_backup_label = true; /* flag if backup_label is there */
|
||||
bool has_recovery_conf = false; /* flag if recovery.conf is there */
|
||||
|
||||
/* repack the options */
|
||||
bool smooth_checkpoint = bkupopt.smooth_checkpoint;
|
||||
|
||||
if (!HAVE_DATABASE(¤t)) {
|
||||
/* check if arclog backup. if arclog backup and no suitable full backup, */
|
||||
@ -112,14 +119,34 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
snprintf(path, lengthof(path), "%s/backup_label", pgdata);
|
||||
make_native_path(path);
|
||||
if (!fileExists(path)) {
|
||||
snprintf(path, lengthof(path), "%s/recovery.conf", pgdata);
|
||||
make_native_path(path);
|
||||
if (!fileExists(path)) {
|
||||
if (verbose)
|
||||
printf(_("backup_label does not exist, stop backup\n"));
|
||||
has_backup_label = false;
|
||||
}
|
||||
snprintf(path, lengthof(path), "%s/recovery.conf", pgdata);
|
||||
make_native_path(path);
|
||||
if (fileExists(path)) {
|
||||
has_recovery_conf = true;
|
||||
}
|
||||
if (!has_backup_label && !has_recovery_conf)
|
||||
{
|
||||
if (verbose)
|
||||
printf(_("backup_label does not exist, stop backup\n"));
|
||||
pg_stop_backup(NULL);
|
||||
elog(ERROR_SYSTEM, _("backup_label does not exist in PGDATA."));
|
||||
}
|
||||
else if (has_recovery_conf)
|
||||
{
|
||||
|
||||
if (!bkupopt.standby_host || !bkupopt.standby_port)
|
||||
{
|
||||
pg_stop_backup(NULL);
|
||||
elog(ERROR_SYSTEM, _("backup_label does not exist in PGDATA."));
|
||||
elog(ERROR_SYSTEM, _("could not specified standby host or port."));
|
||||
}
|
||||
if (!execute_restartpoint(bkupopt))
|
||||
{
|
||||
pg_stop_backup(NULL);
|
||||
elog(ERROR_SYSTEM, _("could not execute restartpoint."));
|
||||
}
|
||||
current.is_from_standby = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -411,6 +438,11 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
/* notify end of backup */
|
||||
pg_stop_backup(¤t);
|
||||
|
||||
/* if backup is from standby, making backup_label from */
|
||||
/* backup.history file. */
|
||||
if (current.is_from_standby)
|
||||
make_backup_label(files);
|
||||
|
||||
/* create file list */
|
||||
create_file_list(files, pgdata, NULL, false);
|
||||
}
|
||||
@ -437,6 +469,25 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
return files;
|
||||
}
|
||||
|
||||
static bool
|
||||
execute_restartpoint(pgBackupOption bkupopt)
|
||||
{
|
||||
PGconn *sby_conn = NULL;
|
||||
const char *tmp_host;
|
||||
const char *tmp_port;
|
||||
tmp_host = pgut_get_host();
|
||||
tmp_port = pgut_get_port();
|
||||
pgut_set_host(bkupopt.standby_host);
|
||||
pgut_set_port(bkupopt.standby_port);
|
||||
sby_conn = reconnect_elevel(ERROR_PG_CONNECT);
|
||||
if (!sby_conn)
|
||||
return false;
|
||||
command("CHECKPOINT", 0, NULL);
|
||||
pgut_set_host(tmp_host);
|
||||
pgut_set_port(tmp_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* backup archived WAL incrementally.
|
||||
*/
|
||||
@ -653,13 +704,7 @@ do_backup_srvlog(parray *backup_list)
|
||||
}
|
||||
|
||||
int
|
||||
do_backup(bool smooth_checkpoint,
|
||||
int keep_arclog_files,
|
||||
int keep_arclog_days,
|
||||
int keep_srvlog_files,
|
||||
int keep_srvlog_days,
|
||||
int keep_data_generations,
|
||||
int keep_data_days)
|
||||
do_backup(pgBackupOption bkupopt)
|
||||
{
|
||||
parray *backup_list;
|
||||
parray *files_database;
|
||||
@ -668,6 +713,14 @@ do_backup(bool smooth_checkpoint,
|
||||
int server_version;
|
||||
int ret;
|
||||
|
||||
/* repack the necesary options */
|
||||
int keep_arclog_files = bkupopt.keep_arclog_files;
|
||||
int keep_arclog_days = bkupopt.keep_arclog_days;
|
||||
int keep_srvlog_files = bkupopt.keep_srvlog_files;
|
||||
int keep_srvlog_days = bkupopt.keep_srvlog_days;
|
||||
int keep_data_generations = bkupopt.keep_data_generations;
|
||||
int keep_data_days = bkupopt.keep_data_days;
|
||||
|
||||
/* PGDATA and BACKUP_MODE are always required */
|
||||
if (pgdata == NULL)
|
||||
elog(ERROR_ARGS, _("required parameter not specified: PGDATA (-D, --pgdata)"));
|
||||
@ -731,8 +784,9 @@ do_backup(bool smooth_checkpoint,
|
||||
current.write_bytes = 0; /* write_bytes is valid always */
|
||||
current.block_size = BLCKSZ;
|
||||
current.wal_block_size = XLOG_BLCKSZ;
|
||||
current.recovery_xid = 0;
|
||||
current.recovery_time = (time_t) 0;
|
||||
current.recovery_xid = 0;
|
||||
current.recovery_time = (time_t) 0;
|
||||
current.is_from_standby = false;
|
||||
|
||||
/* create backup directory and backup.ini */
|
||||
if (!check)
|
||||
@ -754,7 +808,7 @@ current.recovery_time = (time_t) 0;
|
||||
pgut_atexit_push(backup_cleanup, NULL);
|
||||
|
||||
/* backup data */
|
||||
files_database = do_backup_database(backup_list, smooth_checkpoint);
|
||||
files_database = do_backup_database(backup_list, bkupopt);
|
||||
|
||||
/* backup archived WAL */
|
||||
files_arclog = do_backup_arclog(backup_list);
|
||||
@ -822,6 +876,80 @@ current.recovery_time = (time_t) 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
remove_stopinfo_from_backup_label(char *history_file, char *bkup_label)
|
||||
{
|
||||
FILE *read;
|
||||
FILE *write;
|
||||
char buf[MAXPGPATH * 2];
|
||||
|
||||
if ((read = fopen(history_file, "r")) == NULL)
|
||||
elog(ERROR_SYSTEM,
|
||||
_("can't open backup history file for standby backup."));
|
||||
if ((write = fopen(bkup_label, "w")) == NULL)
|
||||
elog(ERROR_SYSTEM,
|
||||
_("can't open backup_label file for standby backup."));
|
||||
while (fgets(buf, lengthof(buf), read) != NULL)
|
||||
{
|
||||
if (strstr(buf, "STOP") - buf == 0)
|
||||
continue;
|
||||
fputs(buf, write);
|
||||
}
|
||||
fclose(write);
|
||||
fclose(read);
|
||||
}
|
||||
|
||||
/*
|
||||
* creating backup_label from backup.history for standby backup.
|
||||
*/
|
||||
void
|
||||
make_backup_label(parray *backup_list)
|
||||
{
|
||||
char dest_path[MAXPGPATH];
|
||||
char src_bkup_history_file[MAXPGPATH];
|
||||
char dst_bkup_label_file[MAXPGPATH];
|
||||
char original_bkup_label_file[MAXPGPATH];
|
||||
parray *bkuped_arc_files = NULL;
|
||||
int i;
|
||||
|
||||
pgBackupGetPath(¤t, dest_path, lengthof(dest_path), DATABASE_DIR);
|
||||
bkuped_arc_files = parray_new();
|
||||
dir_list_file(bkuped_arc_files, arclog_path, NULL, true, false);
|
||||
|
||||
for (i = parray_num(bkuped_arc_files) - 1; i >= 0; i--)
|
||||
{
|
||||
char *current_arc_fname;
|
||||
pgFile *current_arc_file;
|
||||
|
||||
current_arc_file = (pgFile *) parray_get(bkuped_arc_files, i);
|
||||
current_arc_fname = last_dir_separator(current_arc_file->path) + 1;
|
||||
|
||||
if(strlen(current_arc_fname) <= 24) continue;
|
||||
|
||||
copy_file(arclog_path, dest_path, current_arc_file, NO_COMPRESSION);
|
||||
join_path_components(src_bkup_history_file, dest_path, current_arc_fname);
|
||||
join_path_components(dst_bkup_label_file, dest_path, PG_BACKUP_LABEL_FILE);
|
||||
join_path_components(original_bkup_label_file, pgdata, PG_BACKUP_LABEL_FILE);
|
||||
remove_stopinfo_from_backup_label(src_bkup_history_file, dst_bkup_label_file);
|
||||
|
||||
dir_list_file(backup_list, dst_bkup_label_file, NULL, false, true);
|
||||
for (i = 0; i < parray_num(backup_list); i++)
|
||||
{
|
||||
pgFile *file = (pgFile *)parray_get(backup_list, i);
|
||||
if (strcmp(file->path, dst_bkup_label_file) == 0)
|
||||
{
|
||||
struct stat st;
|
||||
stat(dst_bkup_label_file, &st);
|
||||
file->write_size = st.st_size;
|
||||
file->crc = pgFileGetCRC(file);
|
||||
strcpy(file->path, original_bkup_label_file);
|
||||
}
|
||||
}
|
||||
parray_qsort(backup_list, pgFileComparePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get server version and confirm block sizes.
|
||||
*/
|
||||
@ -1030,7 +1158,7 @@ get_xid(PGresult *res, uint32 *xid)
|
||||
/*
|
||||
* Return true if the path is a existing regular file.
|
||||
*/
|
||||
static bool
|
||||
bool
|
||||
fileExists(const char *path)
|
||||
{
|
||||
struct stat buf;
|
||||
|
18
data.c
18
data.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* data.c: compress / uncompress data pages
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -755,14 +755,6 @@ restore_data_file(const char *from_root,
|
||||
elog(ERROR_SYSTEM, _("can't change mode of \"%s\": %s"), to_path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
//aaa if (chown(to_path, file->uid, file->gid) == -1)
|
||||
//aaa {
|
||||
//aaa int errno_tmp = errno;
|
||||
//aaa fclose(in);
|
||||
//aaa fclose(out);
|
||||
//aaa elog(ERROR_SYSTEM, _("can't change owner of \"%s\": %s"), to_path,
|
||||
//aaa strerror(errno_tmp));
|
||||
//aaa }
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
@ -998,14 +990,6 @@ copy_file(const char *from_root, const char *to_root, pgFile *file,
|
||||
elog(ERROR_SYSTEM, _("can't change mode of \"%s\": %s"), to_path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
//aaa if (chown(to_path, file->uid, file->gid) == -1)
|
||||
//aaa {
|
||||
//aaa errno_tmp = errno;
|
||||
//aaa fclose(in);
|
||||
//aaa fclose(out);
|
||||
//aaa elog(ERROR_SYSTEM, _("can't change owner of \"%s\": %s"), to_path,
|
||||
//aaa strerror(errno_tmp));
|
||||
//aaa }
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
3
delete.c
3
delete.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* delete.c: delete backup files.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -13,7 +13,6 @@ static int pgBackupDeleteFiles(pgBackup *backup);
|
||||
static bool checkIfDeletable(pgBackup *backup);
|
||||
|
||||
int
|
||||
//do_delete(pgBackupRange *range)
|
||||
do_delete(pgBackupRange *range, bool force)
|
||||
{
|
||||
int i;
|
||||
|
54
dir.c
54
dir.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* dir.c: directory operation utility.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -31,6 +31,7 @@ const char *pgdata_exclude[] =
|
||||
};
|
||||
|
||||
static pgFile *pgFileNew(const char *path, bool omit_symlink);
|
||||
static int BlackListCompare(const void *str1, const void *str2);
|
||||
|
||||
/* create directory, also create parent directories if necessary */
|
||||
int
|
||||
@ -205,6 +206,12 @@ pgFileCompareMtimeDesc(const void *f1, const void *f2)
|
||||
return -pgFileCompareMtime(f1, f2);
|
||||
}
|
||||
|
||||
static int
|
||||
BlackListCompare(const void *str1, const void *str2)
|
||||
{
|
||||
return strcmp(*(char **) str1, *(char **) str2);
|
||||
}
|
||||
|
||||
/*
|
||||
* List files, symbolic links and directories in the directory "root" and add
|
||||
* pgFile objects to "files". We add "root" to "files" if add_root is true.
|
||||
@ -217,6 +224,42 @@ pgFileCompareMtimeDesc(const void *f1, const void *f2)
|
||||
*/
|
||||
void
|
||||
dir_list_file(parray *files, const char *root, const char *exclude[], bool omit_symlink, bool add_root)
|
||||
{
|
||||
char path[MAXPGPATH];
|
||||
char buf[MAXPGPATH * 2];
|
||||
char black_item[MAXPGPATH * 2];
|
||||
parray *black_list = NULL;
|
||||
|
||||
join_path_components(path, backup_path, PG_BLACK_LIST);
|
||||
if (root && pgdata && strcmp(root, pgdata) == 0 &&
|
||||
fileExists(path))
|
||||
{
|
||||
FILE *black_list_file = NULL;
|
||||
black_list = parray_new();
|
||||
black_list_file = fopen(path, "r");
|
||||
if (black_list_file == NULL)
|
||||
elog(ERROR_SYSTEM, _("can't open black_list: %s"),
|
||||
strerror(errno));
|
||||
while (fgets(buf, lengthof(buf), black_list_file) != NULL)
|
||||
{
|
||||
join_path_components(black_item, pgdata, buf);
|
||||
if (black_item[strlen(black_item) - 1] == '\n')
|
||||
black_item[strlen(black_item) - 1] = '\0';
|
||||
if (black_item[0] == '#' || black_item[0] == '\0')
|
||||
continue;
|
||||
parray_append(black_list, black_item);
|
||||
}
|
||||
fclose(black_list_file);
|
||||
parray_qsort(black_list, BlackListCompare);
|
||||
dir_list_file_internal(files, root, exclude, omit_symlink, add_root, black_list);
|
||||
}
|
||||
else
|
||||
dir_list_file_internal(files, root, exclude, omit_symlink, add_root, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
dir_list_file_internal(parray *files, const char *root, const char *exclude[],
|
||||
bool omit_symlink, bool add_root, parray *black_list)
|
||||
{
|
||||
pgFile *file;
|
||||
|
||||
@ -224,6 +267,13 @@ dir_list_file(parray *files, const char *root, const char *exclude[], bool omit_
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
/* skip if the file is in black_list defined by user */
|
||||
if (black_list && parray_bsearch(black_list, root, BlackListCompare))
|
||||
{
|
||||
/* found in black_list. skip this item */
|
||||
return;
|
||||
}
|
||||
|
||||
if (add_root)
|
||||
parray_append(files, file);
|
||||
|
||||
@ -335,7 +385,7 @@ dir_list_file(parray *files, const char *root, const char *exclude[], bool omit_
|
||||
continue;
|
||||
|
||||
join_path_components(child, file->path, dent->d_name);
|
||||
dir_list_file(files, child, exclude, omit_symlink, true);
|
||||
dir_list_file_internal(files, child, exclude, omit_symlink, true, black_list);
|
||||
}
|
||||
if (errno && errno != ENOENT)
|
||||
{
|
||||
|
@ -28,12 +28,15 @@ Backup options:
|
||||
--keep-arclog-days=DAY keep archived WAL modified in DAY days
|
||||
--keep-srvlog-files=NUM keep NUM of serverlogs
|
||||
--keep-srvlog-days=DAY keep serverlog modified in DAY days
|
||||
--standby-host=HOSTNAME standby host when taking backup from standby
|
||||
--standby-port=PORT standby port when taking backup from standby
|
||||
|
||||
Restore options:
|
||||
--recovery-target-time time stamp up to which recovery will proceed
|
||||
--recovery-target-xid transaction ID up to which recovery will proceed
|
||||
--recovery-target-inclusive whether we stop just after the recovery target
|
||||
--recovery-target-timeline recovering into a particular timeline
|
||||
--hard-copy copying archivelog not symbolic link
|
||||
|
||||
Catalog options:
|
||||
-a, --show-all show deleted backup too
|
||||
@ -54,7 +57,7 @@ Generic options:
|
||||
|
||||
Read the website for details. <http://code.google.com/p/pg-rman/>
|
||||
Report bugs to <http://code.google.com/p/pg-rman/issues/list>.
|
||||
pg_rman 1.2.5
|
||||
pg_rman 1.2.6
|
||||
ERROR: required parameter not specified: BACKUP_PATH (-B, --backup-path)
|
||||
ERROR: required parameter not specified: BACKUP_MODE (-b, --backup-mode)
|
||||
ERROR: required parameter not specified: ARCLOG_PATH (-A, --arclog-path)
|
||||
|
34
pg_rman.c
34
pg_rman.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pg_rman.c: Backup/Recovery manager for PostgreSQL.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -14,7 +14,7 @@
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
const char *PROGRAM_VERSION = "1.2.5";
|
||||
const char *PROGRAM_VERSION = "1.2.6";
|
||||
const char *PROGRAM_URL = "http://code.google.com/p/pg-rman/";
|
||||
const char *PROGRAM_EMAIL = "http://code.google.com/p/pg-rman/issues/list";
|
||||
|
||||
@ -39,12 +39,15 @@ static int keep_srvlog_files = KEEP_INFINITE;
|
||||
static int keep_srvlog_days = KEEP_INFINITE;
|
||||
static int keep_data_generations = KEEP_INFINITE;
|
||||
static int keep_data_days = KEEP_INFINITE;
|
||||
static char *standby_host = NULL;
|
||||
static char *standby_port = NULL;
|
||||
|
||||
/* restore configuration */
|
||||
static char *target_time;
|
||||
static char *target_xid;
|
||||
static char *target_inclusive;
|
||||
static TimeLineID target_tli;
|
||||
static bool is_hard_copy = false;
|
||||
|
||||
/* delete configuration */
|
||||
static bool force;
|
||||
@ -70,6 +73,8 @@ static pgut_option options[] =
|
||||
{ 'b', 's', "with-serverlog" , ¤t.with_serverlog , SOURCE_ENV },
|
||||
{ 'b', 'Z', "compress-data" , ¤t.compress_data , SOURCE_ENV },
|
||||
{ 'b', 'C', "smooth-checkpoint" , &smooth_checkpoint , SOURCE_ENV },
|
||||
{ 's', 12, "standby-host" , &standby_host , SOURCE_ENV },
|
||||
{ 's', 13, "standby-port" , &standby_port , SOURCE_ENV },
|
||||
/* delete options */
|
||||
{ 'b', 'f', "force" , &force , SOURCE_ENV },
|
||||
/* options with only long name (keep-xxx) */
|
||||
@ -84,6 +89,7 @@ static pgut_option options[] =
|
||||
{ 's', 8, "recovery-target-xid" , &target_xid , SOURCE_ENV },
|
||||
{ 's', 9, "recovery-target-inclusive" , &target_inclusive , SOURCE_ENV },
|
||||
{ 'u', 10, "recovery-target-timeline" , &target_tli , SOURCE_ENV },
|
||||
{ 'b', 11, "hard-copy" , &is_hard_copy , SOURCE_ENV },
|
||||
/* catalog options */
|
||||
{ 'b', 'a', "show-all" , &show_all },
|
||||
{ 0 }
|
||||
@ -183,19 +189,28 @@ main(int argc, char *argv[])
|
||||
if (pg_strcasecmp(cmd, "init") == 0)
|
||||
return do_init();
|
||||
else if (pg_strcasecmp(cmd, "backup") == 0)
|
||||
return do_backup(smooth_checkpoint,
|
||||
keep_arclog_files, keep_arclog_days,
|
||||
keep_srvlog_files, keep_srvlog_days,
|
||||
keep_data_generations, keep_data_days);
|
||||
{
|
||||
pgBackupOption bkupopt;
|
||||
bkupopt.smooth_checkpoint = smooth_checkpoint;
|
||||
bkupopt.keep_arclog_files = keep_arclog_files;
|
||||
bkupopt.keep_arclog_days = keep_arclog_days;
|
||||
bkupopt.keep_srvlog_files = keep_srvlog_files;
|
||||
bkupopt.keep_srvlog_days = keep_srvlog_days;
|
||||
bkupopt.keep_data_generations = keep_data_generations;
|
||||
bkupopt.keep_data_days = keep_data_days;
|
||||
bkupopt.standby_host = standby_host;
|
||||
bkupopt.standby_port = standby_port;
|
||||
return do_backup(bkupopt);
|
||||
}
|
||||
else if (pg_strcasecmp(cmd, "restore") == 0){
|
||||
return do_restore(target_time, target_xid, target_inclusive, target_tli);
|
||||
return do_restore(target_time, target_xid,
|
||||
target_inclusive, target_tli, is_hard_copy);
|
||||
}
|
||||
else if (pg_strcasecmp(cmd, "show") == 0)
|
||||
return do_show(&range, show_timeline, show_all);
|
||||
else if (pg_strcasecmp(cmd, "validate") == 0)
|
||||
return do_validate(&range);
|
||||
else if (pg_strcasecmp(cmd, "delete") == 0)
|
||||
// return do_delete(&range);
|
||||
return do_delete(&range, force);
|
||||
else
|
||||
elog(ERROR_ARGS, "invalid command \"%s\"", cmd);
|
||||
@ -236,11 +251,14 @@ pgut_help(bool details)
|
||||
printf(_(" --keep-arclog-days=DAY keep archived WAL modified in DAY days\n"));
|
||||
printf(_(" --keep-srvlog-files=NUM keep NUM of serverlogs\n"));
|
||||
printf(_(" --keep-srvlog-days=DAY keep serverlog modified in DAY days\n"));
|
||||
printf(_(" --standby-host=HOSTNAME standby host when taking backup from standby\n"));
|
||||
printf(_(" --standby-port=PORT standby port when taking backup from standby\n"));
|
||||
printf(_("\nRestore options:\n"));
|
||||
printf(_(" --recovery-target-time time stamp up to which recovery will proceed\n"));
|
||||
printf(_(" --recovery-target-xid transaction ID up to which recovery will proceed\n"));
|
||||
printf(_(" --recovery-target-inclusive whether we stop just after the recovery target\n"));
|
||||
printf(_(" --recovery-target-timeline recovering into a particular timeline\n"));
|
||||
printf(_(" --hard-copy copying archivelog not symbolic link\n"));
|
||||
printf(_("\nCatalog options:\n"));
|
||||
printf(_(" -a, --show-all show deleted backup too\n"));
|
||||
}
|
||||
|
46
pg_rman.h
46
pg_rman.h
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pg_rman.h: Backup/Recovery manager for PostgreSQL.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -32,19 +32,21 @@
|
||||
|
||||
/* Directory/File names */
|
||||
#define DATABASE_DIR "database"
|
||||
#define ARCLOG_DIR "arclog"
|
||||
#define SRVLOG_DIR "srvlog"
|
||||
#define ARCLOG_DIR "arclog"
|
||||
#define SRVLOG_DIR "srvlog"
|
||||
#define RESTORE_WORK_DIR "backup"
|
||||
#define PG_XLOG_DIR "pg_xlog"
|
||||
#define PG_XLOG_DIR "pg_xlog"
|
||||
#define PG_TBLSPC_DIR "pg_tblspc"
|
||||
#define TIMELINE_HISTORY_DIR "timeline_history"
|
||||
#define TIMELINE_HISTORY_DIR "timeline_history"
|
||||
#define BACKUP_INI_FILE "backup.ini"
|
||||
#define PG_RMAN_INI_FILE "pg_rman.ini"
|
||||
#define MKDIRS_SH_FILE "mkdirs.sh"
|
||||
#define DATABASE_FILE_LIST "file_database.txt"
|
||||
#define ARCLOG_FILE_LIST "file_arclog.txt"
|
||||
#define SRVLOG_FILE_LIST "file_srvlog.txt"
|
||||
#define SNAPSHOT_SCRIPT_FILE "snapshot_script"
|
||||
#define SNAPSHOT_SCRIPT_FILE "snapshot_script"
|
||||
#define PG_BACKUP_LABEL_FILE "backup_label"
|
||||
#define PG_BLACK_LIST "black_list"
|
||||
|
||||
/* Snapshot script command */
|
||||
#define SNAPSHOT_FREEZE "freeze"
|
||||
@ -160,8 +162,25 @@ typedef struct pgBackup
|
||||
uint32 block_size;
|
||||
uint32 wal_block_size;
|
||||
|
||||
/* if backup from standby or not */
|
||||
bool is_from_standby;
|
||||
|
||||
} pgBackup;
|
||||
|
||||
typedef struct pgBackupOption
|
||||
{
|
||||
bool smooth_checkpoint;
|
||||
int keep_arclog_files;
|
||||
int keep_arclog_days;
|
||||
int keep_srvlog_files;
|
||||
int keep_srvlog_days;
|
||||
int keep_data_generations;
|
||||
int keep_data_days;
|
||||
char *standby_host;
|
||||
char *standby_port;
|
||||
} pgBackupOption;
|
||||
|
||||
|
||||
/* special values of pgBackup */
|
||||
#define KEEP_INFINITE (INT_MAX)
|
||||
#define BYTES_INVALID (-1)
|
||||
@ -219,21 +238,17 @@ extern pgBackup current;
|
||||
extern const char *pgdata_exclude[];
|
||||
|
||||
/* in backup.c */
|
||||
extern int do_backup(bool smooth_checkpoint,
|
||||
int keep_arclog_files,
|
||||
int keep_arclog_days,
|
||||
int keep_srvlog_files,
|
||||
int keep_srvlog_days,
|
||||
int keep_data_generations,
|
||||
int keep_data_days);
|
||||
extern int do_backup(pgBackupOption bkupopt);
|
||||
extern BackupMode parse_backup_mode(const char *value, int elevel);
|
||||
extern int get_server_version(void);
|
||||
extern bool fileExists(const char *path);
|
||||
|
||||
/* in restore.c */
|
||||
extern int do_restore(const char *target_time,
|
||||
const char *target_xid,
|
||||
const char *target_inclusive,
|
||||
TimeLineID target_tli);
|
||||
TimeLineID target_tli,
|
||||
bool is_hard_copy);
|
||||
|
||||
/* in init.c */
|
||||
extern int do_init(void);
|
||||
@ -242,7 +257,6 @@ extern int do_init(void);
|
||||
extern int do_show(pgBackupRange *range, bool show_timeline, bool show_all);
|
||||
|
||||
/* in delete.c */
|
||||
//extern int do_delete(pgBackupRange *range);
|
||||
extern int do_delete(pgBackupRange *range, bool force);
|
||||
extern void pgBackupDelete(int keep_generations, int keep_days);
|
||||
|
||||
@ -273,6 +287,8 @@ extern int pgBackupCompareIdDesc(const void *f1, const void *f2);
|
||||
|
||||
/* in dir.c */
|
||||
extern void dir_list_file(parray *files, const char *root, const char *exclude[], bool omit_symlink, bool add_root);
|
||||
extern void dir_list_file_internal(parray *files, const char *root, const char *exclude[],
|
||||
bool omit_symlink, bool add_root, parray *black_list);
|
||||
extern void dir_print_mkdirs_sh(FILE *out, const parray *files, const char *root);
|
||||
extern void dir_print_file_list(FILE *out, const parray *files, const char *root, const char *prefix);
|
||||
extern parray *dir_read_file_list(const char *root, const char *file_txt);
|
||||
|
28
pgut/pgut.c
28
pgut/pgut.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pgut.c
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -899,7 +899,6 @@ pgut_connect(int elevel)
|
||||
elog(ERROR_INTERRUPTED, "interrupted");
|
||||
|
||||
#ifndef PGUT_NO_PROMPT
|
||||
// if (prompt_password == DEFAULT) // katsumata
|
||||
if (prompt_password == YES)
|
||||
prompt_for_password(username);
|
||||
#endif
|
||||
@ -963,6 +962,31 @@ disconnect(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* set/get host and port for connecting standby server */
|
||||
const char *
|
||||
pgut_get_host()
|
||||
{
|
||||
return host;
|
||||
}
|
||||
|
||||
const char *
|
||||
pgut_get_port()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
void
|
||||
pgut_set_host(const char *new_host)
|
||||
{
|
||||
host = new_host;
|
||||
}
|
||||
|
||||
void
|
||||
pgut_set_port(const char *new_port)
|
||||
{
|
||||
port = new_port;
|
||||
}
|
||||
|
||||
PGresult *
|
||||
pgut_execute(PGconn* conn, const char *query, int nParams, const char **params, int elevel)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pgut.h
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -120,6 +120,13 @@ extern int pgut_wait(int num, PGconn *connections[], struct timeval *timeout);
|
||||
extern PGconn *reconnect_elevel(int elevel);
|
||||
extern void reconnect(void);
|
||||
extern void disconnect(void);
|
||||
|
||||
extern const char *pgut_get_host(void);
|
||||
extern const char *pgut_get_port(void);
|
||||
extern void pgut_set_host(const char *new_host);
|
||||
extern void pgut_set_port(const char *new_port);
|
||||
|
||||
|
||||
extern PGresult *execute_elevel(const char *query, int nParams, const char **params, int elevel);
|
||||
extern PGresult *execute(const char *query, int nParams, const char **params);
|
||||
extern void command(const char *query, int nParams, const char **params);
|
||||
|
37
restore.c
37
restore.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* restore.c: restore DB cluster and archived WAL.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -19,7 +19,7 @@
|
||||
static void backup_online_files(bool re_recovery);
|
||||
static void restore_online_files(void);
|
||||
static void restore_database(pgBackup *backup);
|
||||
static void restore_archive_logs(pgBackup *backup);
|
||||
static void restore_archive_logs(pgBackup *backup, bool is_hard_copy);
|
||||
static void create_recovery_conf(const char *target_time,
|
||||
const char *target_xid,
|
||||
const char *target_inclusive,
|
||||
@ -39,7 +39,8 @@ int
|
||||
do_restore(const char *target_time,
|
||||
const char *target_xid,
|
||||
const char *target_inclusive,
|
||||
TimeLineID target_tli)
|
||||
TimeLineID target_tli,
|
||||
bool is_hard_copy)
|
||||
{
|
||||
int i;
|
||||
int base_index; /* index of base (full) backup */
|
||||
@ -201,6 +202,7 @@ base_backup_found:
|
||||
continue;
|
||||
|
||||
/* is the backup is necessary for restore to target timeline ? */
|
||||
//if (!satisfy_timeline(timelines, backup) && !satisfy_recovery_target(backup, rt))
|
||||
if (!satisfy_timeline(timelines, backup) || !satisfy_recovery_target(backup, rt))
|
||||
continue;
|
||||
|
||||
@ -242,7 +244,7 @@ base_backup_found:
|
||||
if (!satisfy_timeline(timelines, backup))
|
||||
continue;
|
||||
|
||||
restore_archive_logs(backup);
|
||||
restore_archive_logs(backup, is_hard_copy);
|
||||
|
||||
if (check)
|
||||
{
|
||||
@ -474,7 +476,7 @@ restore_database(pgBackup *backup)
|
||||
* archive directory.
|
||||
*/
|
||||
void
|
||||
restore_archive_logs(pgBackup *backup)
|
||||
restore_archive_logs(pgBackup *backup, bool is_hard_copy)
|
||||
{
|
||||
int i;
|
||||
char timestamp[100];
|
||||
@ -549,12 +551,27 @@ restore_archive_logs(pgBackup *backup)
|
||||
elog(ERROR_SYSTEM, _("can't remove file \"%s\": %s"), path,
|
||||
strerror(errno));
|
||||
|
||||
if ((symlink(file->path, path) == -1))
|
||||
elog(ERROR_SYSTEM, _("can't create link to \"%s\": %s"),
|
||||
file->path, strerror(errno));
|
||||
if (!is_hard_copy)
|
||||
{
|
||||
/* create symlink */
|
||||
if ((symlink(file->path, path) == -1))
|
||||
elog(ERROR_SYSTEM, _("can't create link to \"%s\": %s"),
|
||||
file->path, strerror(errno));
|
||||
|
||||
if (verbose)
|
||||
printf(_("linked\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create hard-copy */
|
||||
if (!copy_file(base_path, arclog_path, file, NO_COMPRESSION))
|
||||
elog(ERROR_SYSTEM, _("can't copy to \"%s\": %s"),
|
||||
file->path, strerror(errno));
|
||||
|
||||
if (verbose)
|
||||
printf(_("copied\n"));
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf(_("linked\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,6 @@ while [ $# -gt 0 ]; do
|
||||
esac
|
||||
done
|
||||
|
||||
export LANG=C
|
||||
|
||||
# delete old database cluster
|
||||
pg_ctl stop -m immediate > /dev/null 2>&1
|
||||
rm -rf $PGDATA
|
||||
@ -140,7 +138,7 @@ pg_rman -w -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/result
|
||||
# validate all backup
|
||||
pg_rman validate `date +%Y` --verbose > $BASE_PATH/results/log_validate1 2>&1
|
||||
pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show0 2>&1
|
||||
pg_dumpall -p $TEST_PGPORT > $BASE_PATH/results/dump_before_rtx.sql
|
||||
pg_dumpall > $BASE_PATH/results/dump_before_rtx.sql
|
||||
target_xid=`psql -p $TEST_PGPORT pgbench -tAq -c "INSERT INTO pgbench_history VALUES (1) RETURNING(xmin);"`
|
||||
psql -p $TEST_PGPORT postgres -c "checkpoint"
|
||||
#pg_rman -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/results/log_incr2 2>&1
|
||||
@ -158,7 +156,7 @@ sleep `expr $DURATION / 2`
|
||||
pg_ctl stop -m immediate > /dev/null 2>&1
|
||||
cp -rp $PGDATA $PGDATA.bak
|
||||
pg_ctl start -w -t 3600 > /dev/null 2>&1
|
||||
pg_dumpall -p $TEST_PGPORT > $BASE_PATH/results/dump_before.sql
|
||||
pg_dumpall > $BASE_PATH/results/dump_before.sql
|
||||
|
||||
# revert to crushed cluster
|
||||
pg_ctl stop > /dev/null 2>&1
|
||||
@ -213,7 +211,7 @@ find $BACKUP_PATH/backup/srvlog -type f | wc -l
|
||||
pg_ctl start -w -t 3600 > /dev/null 2>&1
|
||||
|
||||
# compare recovery results
|
||||
pg_dumpall -p $TEST_PGPORT > $BASE_PATH/results/dump_after.sql
|
||||
pg_dumpall > $BASE_PATH/results/dump_after.sql
|
||||
diff $BASE_PATH/results/dump_before.sql $BASE_PATH/results/dump_after.sql
|
||||
|
||||
# take a backup and delete backed up online files
|
||||
@ -256,7 +254,7 @@ grep -c "recovery_target_" $PGDATA/recovery.conf
|
||||
# recovery database
|
||||
pg_ctl start -w -t 3600 > /dev/null 2>&1
|
||||
|
||||
pg_dumpall -p $TEST_PGPORT > $BASE_PATH/results/dump_after_rtx.sql
|
||||
pg_dumpall > $BASE_PATH/results/dump_after_rtx.sql
|
||||
diff $BASE_PATH/results/dump_before_rtx.sql $BASE_PATH/results/dump_after_rtx.sql
|
||||
|
||||
# show timeline
|
||||
|
5
xlog.c
5
xlog.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* xlog.c: Parse WAL files.
|
||||
*
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,6 +29,7 @@ typedef struct MemoryContextData *MemoryContext;
|
||||
#define XLOG_PAGE_MAGIC_v90 0xD064 /* 9.0 */
|
||||
#define XLOG_PAGE_MAGIC_v91 0xD066 /* 9.1 */
|
||||
#define XLOG_PAGE_MAGIC_v92 0xD071 /* 9.2 */
|
||||
#define XLOG_PAGE_MAGIC_v93 0xD075 /* 9.2 */
|
||||
|
||||
/*
|
||||
* XLogLongPageHeaderData is modified in 8.3, but the layout is compatible
|
||||
@ -81,6 +82,8 @@ xlog_is_complete_wal(const pgFile *file, int server_version)
|
||||
xlog_page_magic = XLOG_PAGE_MAGIC_v91;
|
||||
else if (server_version < 90300)
|
||||
xlog_page_magic = XLOG_PAGE_MAGIC_v92;
|
||||
else if (server_version < 90400)
|
||||
xlog_page_magic = XLOG_PAGE_MAGIC_v93;
|
||||
else
|
||||
return false; /* not supported */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user