mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-01-07 13:40:17 +02:00
revised for pg_rman1.2.2
git-svn-id: http://pg-rman.googlecode.com/svn/trunk@48 182aca00-e38e-11de-a668-6fd11605f5ce
This commit is contained in:
parent
ae6c0e0c55
commit
78eed96f63
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
|
||||
Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||
Portions Copyright (c) 1994, The Regents of the University of California
|
||||
|
2
Makefile
2
Makefile
@ -24,7 +24,7 @@ OBJS = $(SRCS:.c=.o)
|
||||
PG_CPPFLAGS = -I$(libpq_srcdir)
|
||||
PG_LIBS = $(libpq_pgport)
|
||||
|
||||
REGRESS = option init show_validate backup_restore snapshot
|
||||
REGRESS = option init show_validate backup_restore
|
||||
|
||||
ifdef USE_PGXS
|
||||
PG_CONFIG = pg_config
|
||||
|
@ -9,7 +9,7 @@
|
||||
## Set general information for pg_rman.
|
||||
Summary: Backup and Recovery Tool for PostgreSQL
|
||||
Name: pg_rman
|
||||
Version: 1.2.1
|
||||
Version: 1.2.0
|
||||
Release: 1%{?dist}
|
||||
License: BSD
|
||||
Group: Applications/Databases
|
||||
@ -58,7 +58,6 @@ rm -rf %{buildroot}
|
||||
|
||||
# History of pg_rman.
|
||||
%changelog
|
||||
* Mon Jun 20 2011 - Tomonari Katsumata <t.katsumata1122@gmail.com> 1.2.1-1
|
||||
* 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
|
||||
|
92
backup.c
92
backup.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* backup.c: backup DB cluster, archived WAL, serverlog.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -41,6 +41,7 @@ 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 void delete_arclog_link(void);
|
||||
static void delete_online_wal_backup(void);
|
||||
@ -75,8 +76,26 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
XLogRecPtr *lsn = NULL;
|
||||
char prev_file_txt[MAXPGPATH]; /* path of the previous backup list file */
|
||||
|
||||
if (!HAVE_DATABASE(¤t))
|
||||
return NULL;
|
||||
if (!HAVE_DATABASE(¤t)) {
|
||||
/* check if arclog backup. if arclog backup and no suitable full backup, */
|
||||
/* take full backup instead. */
|
||||
if (HAVE_ARCLOG(¤t)) {
|
||||
pgBackup *prev_backup;
|
||||
|
||||
/* find last completed database backup */
|
||||
prev_backup = catalog_get_last_data_backup(backup_list);
|
||||
if (prev_backup == NULL)
|
||||
{
|
||||
elog(ERROR_SYSTEM, _("There is indeed a full backup but it is not validated."
|
||||
"So I can't take any arclog backup."
|
||||
"Please validate it and retry."));
|
||||
/// elog(INFO, _("no previous full backup, performing a full backup instead"));
|
||||
/// current.backup_mode = BACKUP_MODE_FULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elog(INFO, _("database backup start"));
|
||||
|
||||
@ -89,6 +108,16 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
strncat(label, " with pg_rman", lengthof(label));
|
||||
pg_start_backup(label, smooth_checkpoint, ¤t);
|
||||
|
||||
/* If backup_label does not exist in $PGDATA, stop taking backup */
|
||||
snprintf(path, lengthof(path), "%s/backup_label", pgdata);
|
||||
make_native_path(path);
|
||||
if (!fileExists(path)) {
|
||||
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."));
|
||||
}
|
||||
|
||||
/*
|
||||
* list directories and symbolic links with the physical path to make
|
||||
* mkdirs.sh
|
||||
@ -127,10 +156,13 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
|
||||
|
||||
/* find last completed database backup */
|
||||
prev_backup = catalog_get_last_data_backup(backup_list);
|
||||
if (prev_backup == NULL)
|
||||
if (prev_backup == NULL || prev_backup->tli != current.tli)
|
||||
{
|
||||
elog(INFO, _("no previous full backup, do a full backup instead"));
|
||||
current.backup_mode = BACKUP_MODE_FULL;
|
||||
elog(ERROR_SYSTEM, _("There is indeed a full backup but it is not validated."
|
||||
"So I can't take any incremental backup."
|
||||
"Please validate it and retry."));
|
||||
/// elog(INFO, _("no previous full backup, performing a full backup instead"));
|
||||
/// current.backup_mode = BACKUP_MODE_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -440,7 +472,7 @@ do_backup_arclog(parray *backup_list)
|
||||
*/
|
||||
prev_backup = catalog_get_last_arclog_backup(backup_list);
|
||||
if (verbose && prev_backup == NULL)
|
||||
printf(_("no previous full backup, do a full backup instead\n"));
|
||||
printf(_("no previous full backup, performing a full backup instead\n"));
|
||||
|
||||
if (prev_backup)
|
||||
{
|
||||
@ -564,7 +596,7 @@ do_backup_srvlog(parray *backup_list)
|
||||
*/
|
||||
prev_backup = catalog_get_last_srvlog_backup(backup_list);
|
||||
if (verbose && prev_backup == NULL)
|
||||
printf(_("no previous full backup, do a full backup instead\n"));
|
||||
printf(_("no previous full backup, performing a full backup instead\n"));
|
||||
|
||||
if (prev_backup)
|
||||
{
|
||||
@ -695,6 +727,8 @@ 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;
|
||||
|
||||
/* create backup directory and backup.ini */
|
||||
if (!check)
|
||||
@ -708,6 +742,9 @@ do_backup(bool smooth_checkpoint,
|
||||
|
||||
/* get list of backups already taken */
|
||||
backup_list = catalog_get_backup_list(NULL);
|
||||
if(!backup_list){
|
||||
elog(ERROR_SYSTEM, _("can't process any more."));
|
||||
}
|
||||
|
||||
/* set the error processing function for the backup process */
|
||||
pgut_atexit_push(backup_cleanup, NULL);
|
||||
@ -893,6 +930,12 @@ wait_for_archive(pgBackup *backup, const char *sql)
|
||||
elog(LOG, "%s() wait for %s", __FUNCTION__, ready_path);
|
||||
|
||||
PQclear(res);
|
||||
|
||||
res = execute(TXID_CURRENT_SQL, 0, NULL);
|
||||
if(backup != NULL){
|
||||
get_xid(res, &backup->recovery_xid);
|
||||
backup->recovery_time = time(NULL);
|
||||
}
|
||||
disconnect();
|
||||
|
||||
/* wait until switched WAL is archived */
|
||||
@ -960,6 +1003,26 @@ get_lsn(PGresult *res, TimeLineID *timeline, XLogRecPtr *lsn)
|
||||
lsn->xrecoff += off_upper << 24;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get XID from result of txid_current() after pg_stop_backup().
|
||||
*/
|
||||
static void
|
||||
get_xid(PGresult *res, uint32 *xid)
|
||||
{
|
||||
if(res == NULL || PQntuples(res) != 1 || PQnfields(res) != 1)
|
||||
elog(ERROR_PG_COMMAND,
|
||||
_("result of txid_current() is invalid: %s"),
|
||||
PQerrorMessage(connection));
|
||||
|
||||
if(sscanf(PQgetvalue(res, 0, 0), "%u", xid) != 1)
|
||||
{
|
||||
elog(ERROR_PG_COMMAND,
|
||||
_("result of txid_current() is invalid: %s"),
|
||||
PQerrorMessage(connection));
|
||||
}
|
||||
elog(LOG, "%s():%s", __FUNCTION__, PQgetvalue(res, 0, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the path is a existing regular file.
|
||||
*/
|
||||
@ -1055,6 +1118,11 @@ backup_files(const char *from_root,
|
||||
|
||||
pgFile *file = (pgFile *) parray_get(files, i);
|
||||
|
||||
/* If current time is rewinded, abort this backup. */
|
||||
if(tv.tv_sec < file->mtime){
|
||||
elog(ERROR_SYSTEM, _("current time may be rewound. Please retry with full backup mode."));
|
||||
}
|
||||
|
||||
/* check for interrupt */
|
||||
if (interrupted)
|
||||
elog(ERROR_INTERRUPTED, _("interrupted during backup"));
|
||||
@ -1101,8 +1169,9 @@ backup_files(const char *from_root,
|
||||
char dirpath[MAXPGPATH];
|
||||
|
||||
join_path_components(dirpath, to_root, JoinPathEnd(file->path, from_root));
|
||||
if (!check)
|
||||
if (!check){
|
||||
dir_create_dir(dirpath, DIR_PERMISSION);
|
||||
}
|
||||
if (verbose)
|
||||
printf(_("directory\n"));
|
||||
}
|
||||
@ -1143,7 +1212,7 @@ backup_files(const char *from_root,
|
||||
prev_file = *p;
|
||||
}
|
||||
|
||||
if (prev_file && prev_file->mtime >= file->mtime)
|
||||
if (prev_file && prev_file->mtime == file->mtime)
|
||||
{
|
||||
/* record as skipped file in file_xxx.txt */
|
||||
file->write_size = BYTES_INVALID;
|
||||
@ -1158,7 +1227,8 @@ backup_files(const char *from_root,
|
||||
* file should contain all modifications at the clock of mtime.
|
||||
* timer resolution of ext3 file system is one second.
|
||||
*/
|
||||
if (tv.tv_sec <= file->mtime)
|
||||
|
||||
if (tv.tv_sec == file->mtime)
|
||||
{
|
||||
/* update time and recheck */
|
||||
gettimeofday(&tv, NULL);
|
||||
|
18
catalog.c
18
catalog.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* catalog.c: backup catalog opration
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -364,6 +364,12 @@ pgBackupWriteResultSection(FILE *out, pgBackup *backup)
|
||||
time2iso(timestamp, lengthof(timestamp), backup->end_time);
|
||||
fprintf(out, "END_TIME='%s'\n", timestamp);
|
||||
}
|
||||
fprintf(out, "RECOVERY_XID=%u\n", backup->recovery_xid);
|
||||
if (backup->recovery_time > 0)
|
||||
{
|
||||
time2iso(timestamp, lengthof(timestamp), backup->recovery_time);
|
||||
fprintf(out, "RECOVERY_TIME='%s'\n", timestamp);
|
||||
}
|
||||
|
||||
if (backup->total_data_bytes != BYTES_INVALID)
|
||||
fprintf(out, "TOTAL_DATA_BYTES=" INT64_FORMAT "\n",
|
||||
@ -434,6 +440,8 @@ catalog_read_ini(const char *path)
|
||||
{ 's', 0, "stop-lsn" , NULL, SOURCE_ENV },
|
||||
{ 't', 0, "start-time" , NULL, SOURCE_ENV },
|
||||
{ 't', 0, "end-time" , NULL, SOURCE_ENV },
|
||||
{ 'u', 0, "recovery-xid" , NULL, SOURCE_ENV },
|
||||
{ 't', 0, "recovery-time" , NULL, SOURCE_ENV },
|
||||
{ 'I', 0, "total-data-bytes" , NULL, SOURCE_ENV },
|
||||
{ 'I', 0, "read-data-bytes" , NULL, SOURCE_ENV },
|
||||
{ 'I', 0, "read-arclog-bytes" , NULL, SOURCE_ENV },
|
||||
@ -445,6 +453,10 @@ catalog_read_ini(const char *path)
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
if (access(path, F_OK) != 0){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
backup = pgut_new(pgBackup);
|
||||
catalog_init_config(backup);
|
||||
|
||||
@ -457,6 +469,8 @@ catalog_read_ini(const char *path)
|
||||
options[i++].var = &stop_lsn;
|
||||
options[i++].var = &backup->start_time;
|
||||
options[i++].var = &backup->end_time;
|
||||
options[i++].var = &backup->recovery_xid;
|
||||
options[i++].var = &backup->recovery_time;
|
||||
options[i++].var = &backup->total_data_bytes;
|
||||
options[i++].var = &backup->read_data_bytes;
|
||||
options[i++].var = &backup->read_arclog_bytes;
|
||||
@ -601,6 +615,8 @@ catalog_init_config(pgBackup *backup)
|
||||
backup->stop_lsn.xrecoff = 0;
|
||||
backup->start_time = (time_t) 0;
|
||||
backup->end_time = (time_t) 0;
|
||||
backup->recovery_xid = 0;
|
||||
backup->recovery_time = (time_t) 0;
|
||||
backup->total_data_bytes = BYTES_INVALID;
|
||||
backup->read_data_bytes = BYTES_INVALID;
|
||||
backup->read_arclog_bytes = BYTES_INVALID;
|
||||
|
2
clean.c
2
clean.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* clean.c: cleanup backup files.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
18
data.c
18
data.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* data.c: compress / uncompress data pages
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -756,6 +756,14 @@ 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);
|
||||
@ -992,6 +1000,14 @@ 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);
|
||||
|
@ -7,7 +7,7 @@ TIMELINEID=1
|
||||
START_LSN=0/0b40c800
|
||||
STOP_LSN=0/0b4c8020
|
||||
START_TIME='2009-06-03 17:05:53'
|
||||
END_TIME='****-**-** **:**:**'
|
||||
END_TIME='2009-06-03 17:05:53'
|
||||
TOTAL_DATA_BYTES=-1
|
||||
READ_DATA_BYTES=-1
|
||||
READ_ARCLOG_BYTES=-1
|
||||
|
2
db.c
2
db.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* db.c: SQLite3 access module
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
38
delete.c
38
delete.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* delete.c: delete backup files.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -10,14 +10,17 @@
|
||||
#include "pg_rman.h"
|
||||
|
||||
static int pgBackupDeleteFiles(pgBackup *backup);
|
||||
static bool checkIfDeletable(pgBackup *backup);
|
||||
|
||||
int
|
||||
do_delete(pgBackupRange *range)
|
||||
//do_delete(pgBackupRange *range)
|
||||
do_delete(pgBackupRange *range, bool force)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
parray *backup_list;
|
||||
bool do_delete;
|
||||
bool force_delete;
|
||||
|
||||
/* DATE are always required */
|
||||
if (!pgBackupRangeIsValid(range))
|
||||
@ -29,20 +32,31 @@ do_delete(pgBackupRange *range)
|
||||
elog(ERROR_SYSTEM, _("can't lock backup catalog."));
|
||||
else if (ret == 1)
|
||||
elog(ERROR_ALREADY_RUNNING,
|
||||
_("another pg_rman is running, stop restore."));
|
||||
_("another pg_rman is running, stop delete."));
|
||||
|
||||
/* get list of backups. */
|
||||
backup_list = catalog_get_backup_list(NULL);
|
||||
if(!backup_list){
|
||||
elog(ERROR_SYSTEM, _("can't process any more."));
|
||||
}
|
||||
|
||||
do_delete = false;
|
||||
force_delete = false;
|
||||
/* find delete target backup. */
|
||||
for (i = 0; i < parray_num(backup_list); i++)
|
||||
{
|
||||
pgBackup *backup = (pgBackup *)parray_get(backup_list, i);
|
||||
|
||||
if(force)
|
||||
force_delete = checkIfDeletable(backup);
|
||||
|
||||
/* delete backup and update status to DELETED */
|
||||
if (do_delete)
|
||||
if (do_delete || force_delete)
|
||||
{
|
||||
/* check for interrupt */
|
||||
if (interrupted)
|
||||
elog(ERROR_INTERRUPTED, _("interrupted during delete backup"));
|
||||
|
||||
pgBackupDeleteFiles(backup);
|
||||
continue;
|
||||
}
|
||||
@ -76,6 +90,7 @@ pgBackupDelete(int keep_generations, int keep_days)
|
||||
int backup_num;
|
||||
time_t days_threshold = current.start_time - (keep_days * 60 * 60 * 24);
|
||||
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
char generations_str[100];
|
||||
@ -123,7 +138,8 @@ pgBackupDelete(int keep_generations, int keep_days)
|
||||
backup_num++;
|
||||
|
||||
/* do not include the latest full backup in a count. */
|
||||
if (backup_num - 1 <= keep_generations)
|
||||
// if (backup_num - 1 <= keep_generations)
|
||||
if (backup_num <= keep_generations)
|
||||
{
|
||||
elog(LOG, "%s() backup are only %d", __FUNCTION__, backup_num);
|
||||
continue;
|
||||
@ -233,3 +249,15 @@ pgBackupDeleteFiles(pgBackup *backup)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
checkIfDeletable(pgBackup *backup)
|
||||
{
|
||||
/* find latest full backup. */
|
||||
if (backup->status != BACKUP_STATUS_OK &&
|
||||
backup->status != BACKUP_STATUS_DELETED &&
|
||||
backup->status != BACKUP_STATUS_DONE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
11
dir.c
11
dir.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* dir.c: directory operation utility.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -363,11 +363,13 @@ dir_print_mkdirs_sh(FILE *out, const parray *files, const char *root)
|
||||
pgFile *file = (pgFile *) parray_get(files, i);
|
||||
if (S_ISDIR(file->mode))
|
||||
{
|
||||
if (strstr(file->path, root) == file->path)
|
||||
if (strstr(file->path, root) == file->path) {
|
||||
fprintf(out, "mkdir -m 700 -p %s\n", file->path + strlen(root)
|
||||
+ 1);
|
||||
else
|
||||
}
|
||||
else {
|
||||
fprintf(out, "mkdir -m 700 -p %s\n", file->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,8 +541,9 @@ dir_copy_files(const char *from_root, const char *to_root)
|
||||
if (verbose && !check)
|
||||
printf(_("create directory \"%s\"\n"),
|
||||
file->path + strlen(from_root) + 1);
|
||||
if (!check)
|
||||
if (!check) {
|
||||
dir_create_dir(to_path, DIR_PERMISSION);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if(S_ISREG(file->mode))
|
||||
|
@ -15,13 +15,13 @@ diff files in BACKUP_PATH/backup/pg_xlog
|
||||
1
|
||||
diff files in BACKUP_PATH/backup/pg_xlog
|
||||
# of files in BACKUP_PATH/backup/srvlog
|
||||
2
|
||||
1
|
||||
full database backup after recovery
|
||||
CHECKPOINT
|
||||
# of files in BACKUP_PATH/backup/pg_xlog
|
||||
0
|
||||
# of files in BACKUP_PATH/backup/srvlog
|
||||
2
|
||||
1
|
||||
# of symbolic links in ARCLOG_PATH
|
||||
0
|
||||
# of files in BACKUP_PATH/timeline_history
|
||||
|
@ -1,6 +1,5 @@
|
||||
\! rm -rf results/init_test
|
||||
\! pg_rman init -B results/init_test --quiet;echo $?
|
||||
WARNING: ARCLOG_PATH is not set because archive_command is empty
|
||||
\! pg_rman init -B ${PWD}/results/init_test --quiet;echo $?
|
||||
0
|
||||
\! find results/init_test | xargs ls -Fd | sort
|
||||
results/init_test/
|
||||
@ -9,6 +8,6 @@ results/init_test/backup/pg_xlog/
|
||||
results/init_test/backup/srvlog/
|
||||
results/init_test/pg_rman.ini
|
||||
results/init_test/timeline_history/
|
||||
\! pg_rman init -B results/init_test --quiet;echo $?
|
||||
ERROR: backup catalog already exist.
|
||||
\! pg_rman init -B ${PWD}/results/init_test --quiet;echo $?
|
||||
ERROR: backup catalog already exist. and it's not empty.
|
||||
2
|
||||
|
@ -54,7 +54,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.1.2
|
||||
pg_rman 1.2.2
|
||||
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)
|
||||
@ -62,11 +62,11 @@ ERROR: required parameter not specified: ARCLOG_PATH (-A, --arclog-path)
|
||||
ERROR: required parameter not specified: ARCLOG_PATH (-A, --arclog-path)
|
||||
ERROR: invalid backup-mode "bad"
|
||||
ERROR: required delete range option not specified: delete DATE
|
||||
INFO: validate: 2009-05-31 17:05:53
|
||||
INFO: validate: 2009-06-01 17:05:53
|
||||
INFO: validate: 2009-05-31 17:05:53 backup and archive log files by CRC
|
||||
INFO: validate: 2009-06-01 17:05:53 backup and archive log files by CRC
|
||||
WARNING: CRC of backup file "PG_VERSION" must be 0 but FEF71BC1
|
||||
WARNING: backup 2009-06-01 17:05:53 is corrupted
|
||||
WARNING: syntax error in " = INFINITE".
|
||||
WARNING: syntax error in " = INFINITE"
|
||||
ERROR: required parameter not specified: BACKUP_MODE (-b, --backup-mode)
|
||||
ERROR: invalid backup-mode ""
|
||||
ERROR: required parameter not specified: ARCLOG_PATH (-A, --arclog-path)
|
||||
|
@ -1,35 +1,35 @@
|
||||
-- test show command
|
||||
\! rm -rf results/sample_backup
|
||||
\! cp -rp data/sample_backup results/sample_backup
|
||||
\! pg_rman show -B results/sample_backup
|
||||
\! rm -rf ${PWD}/results/sample_backup
|
||||
\! cp -rp data/sample_backup ${PWD}/results/sample_backup
|
||||
\! pg_rman show -B ${PWD}/results/sample_backup
|
||||
============================================================================
|
||||
Start Time Total Data WAL Log Backup Status
|
||||
============================================================================
|
||||
2009-06-03 17:05:53 ---- ---- ---- ---- ---- ---- RUNNING
|
||||
2009-06-03 17:05:53 0m ---- ---- ---- ---- ---- RUNNING
|
||||
2009-06-01 17:05:53 3m ---- 9223PB 16MB ---- 162MB DONE
|
||||
2009-05-31 17:05:53 3m 1242MB ---- 9223PB ---- 242MB DONE
|
||||
\! pg_rman validate -B results/sample_backup 2009-05-31 17:05:53 --debug
|
||||
INFO: validate: 2009-05-31 17:05:53
|
||||
\! pg_rman validate -B ${PWD}/results/sample_backup 2009-05-31 17:05:53 --debug
|
||||
INFO: validate: 2009-05-31 17:05:53 backup and archive log files by CRC
|
||||
LOG: database files...
|
||||
LOG: (1/1) PG_VERSION
|
||||
LOG: archive WAL files...
|
||||
LOG: backup 2009-05-31 17:05:53 is valid
|
||||
\! pg_rman validate -B results/sample_backup 2009-06-01 17:05:53 --debug
|
||||
INFO: validate: 2009-06-01 17:05:53
|
||||
\! pg_rman validate -B ${PWD}/results/sample_backup 2009-06-01 17:05:53 --debug
|
||||
INFO: validate: 2009-06-01 17:05:53 backup and archive log files by CRC
|
||||
LOG: database files...
|
||||
LOG: (1/1) PG_VERSION
|
||||
WARNING: CRC of backup file "PG_VERSION" must be 0 but FEF71BC1
|
||||
LOG: archive WAL files...
|
||||
WARNING: backup 2009-06-01 17:05:53 is corrupted
|
||||
\! pg_rman show -a -B results/sample_backup
|
||||
\! pg_rman show -a -B ${PWD}/results/sample_backup
|
||||
============================================================================
|
||||
Start Time Total Data WAL Log Backup Status
|
||||
============================================================================
|
||||
2009-06-03 17:05:53 ---- ---- ---- ---- ---- ---- RUNNING
|
||||
2009-06-03 17:05:53 0m ---- ---- ---- ---- ---- RUNNING
|
||||
2009-06-02 17:05:03 0m ---- ---- ---- 4335kB 162MB DELETED
|
||||
2009-06-01 17:05:53 3m ---- 9223PB 16MB ---- 162MB CORRUPT
|
||||
2009-05-31 17:05:53 3m 1242MB ---- 9223PB ---- 242MB OK
|
||||
\! pg_rman show 2009-06-01 17:05:53 -B results/sample_backup
|
||||
\! pg_rman show 2009-06-01 17:05:53 -B ${PWD}/results/sample_backup
|
||||
# configuration
|
||||
BACKUP_MODE=INCREMENTAL
|
||||
WITH_SERVERLOG=false
|
||||
@ -40,10 +40,10 @@ START_LSN=0/0b40c800
|
||||
STOP_LSN=0/0b4c8020
|
||||
START_TIME='2009-06-01 17:05:53'
|
||||
END_TIME='2009-06-01 17:09:13'
|
||||
RECOVERY_XID=0
|
||||
TOTAL_DATA_BYTES=1242102558
|
||||
READ_DATA_BYTES=9223372036854775807
|
||||
READ_ARCLOG_BYTES=16777216
|
||||
READ_SRVLOG_BYTES=-1
|
||||
WRITE_BYTES=162372983
|
||||
BLOCK_SIZE=8192
|
||||
XLOG_BLOCK_SIZE=8192
|
||||
|
2
file.c
2
file.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* file.c:
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
27
init.c
27
init.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* init.c: manage backup catalog.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -10,10 +10,19 @@
|
||||
#include "pg_rman.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
static void parse_postgresql_conf(const char *path, char **log_directory,
|
||||
char **archive_command);
|
||||
|
||||
/*
|
||||
* selects function for scandir.
|
||||
*/
|
||||
static int selects(const struct dirent *dir)
|
||||
{
|
||||
return dir->d_name[0] != '.';
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize backup catalog.
|
||||
*/
|
||||
@ -25,8 +34,14 @@ do_init(void)
|
||||
char *archive_command = NULL;
|
||||
FILE *fp;
|
||||
|
||||
if (access(backup_path, F_OK) == 0)
|
||||
elog(ERROR, _("backup catalog already exist."));
|
||||
struct dirent **dp;
|
||||
int results;
|
||||
if (access(backup_path, F_OK) == 0){
|
||||
results = scandir(backup_path, &dp, selects, NULL);
|
||||
if(results != 0){
|
||||
elog(ERROR, _("backup catalog already exist. and it's not empty."));
|
||||
}
|
||||
}
|
||||
|
||||
/* create backup catalog root directory */
|
||||
dir_create_dir(backup_path, DIR_PERMISSION);
|
||||
@ -98,9 +113,11 @@ do_init(void)
|
||||
elog(INFO, "ARCLOG_PATH is set to '%s'", arclog_path);
|
||||
}
|
||||
else if (archive_command && archive_command[0])
|
||||
elog(WARNING, "ARCLOG_PATH is not set because failed to parse archive_command '%s'", archive_command);
|
||||
elog(WARNING, "ARCLOG_PATH is not set because failed to parse archive_command '%s'."
|
||||
"Please set ARCLOG_PATH in pg_rman.ini or environmental variable", archive_command);
|
||||
else
|
||||
elog(WARNING, "ARCLOG_PATH is not set because archive_command is empty");
|
||||
elog(WARNING, "ARCLOG_PATH is not set because archive_command is empty."
|
||||
"Please set ARCLOG_PATH in pg_rman.ini or environmental variable");
|
||||
|
||||
/* set SRVLOG_PATH refered with log_directory */
|
||||
if (srvlog_path == NULL)
|
||||
|
2
parray.c
2
parray.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* parray.c: pointer array collection.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
2
parray.h
2
parray.h
@ -2,7 +2,7 @@
|
||||
*
|
||||
* parray.h: pointer array collection.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
2
pg_ctl.c
2
pg_ctl.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pg_ctl.c: operations for control file
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
36
pg_rman.c
36
pg_rman.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pg_rman.c: Backup/Recovery manager for PostgreSQL.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -13,7 +13,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
const char *PROGRAM_VERSION = "1.2.1";
|
||||
const char *PROGRAM_VERSION = "1.2.2";
|
||||
const char *PROGRAM_URL = "http://code.google.com/p/pg-rman/";
|
||||
const char *PROGRAM_EMAIL = "http://code.google.com/p/pg-rman/issues/list";
|
||||
|
||||
@ -45,6 +45,9 @@ static char *target_xid;
|
||||
static char *target_inclusive;
|
||||
static TimeLineID target_tli;
|
||||
|
||||
/* delete configuration */
|
||||
static bool force;
|
||||
|
||||
/* show configuration */
|
||||
static bool show_all = false;
|
||||
|
||||
@ -66,6 +69,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 },
|
||||
/* delete options */
|
||||
{ 'b', 'f', "force" , &force , SOURCE_ENV },
|
||||
/* options with only long name (keep-xxx) */
|
||||
{ 'i', 1, "keep-data-generations" , &keep_data_generations, SOURCE_ENV },
|
||||
{ 'i', 2, "keep-data-days" , &keep_data_days , SOURCE_ENV },
|
||||
@ -139,6 +144,13 @@ main(int argc, char *argv[])
|
||||
if (backup_path)
|
||||
{
|
||||
char path[MAXPGPATH];
|
||||
/* Check if backup_path is directory. */
|
||||
struct stat stat_buf;
|
||||
int rc = stat(backup_path, &stat_buf);
|
||||
if(rc != -1 && !S_ISDIR(stat_buf.st_mode)){
|
||||
/* If rc == -1, there is no file or directory. So it's OK. */
|
||||
elog(ERROR_ARGS, "-B, --backup-path must be a path to directory");
|
||||
}
|
||||
|
||||
join_path_components(path, backup_path, PG_RMAN_INI_FILE);
|
||||
pgut_readopt(path, options, ERROR_ARGS);
|
||||
@ -149,6 +161,8 @@ main(int argc, char *argv[])
|
||||
elog(ERROR_ARGS, "required parameter not specified: BACKUP_PATH (-B, --backup-path)");
|
||||
|
||||
/* path must be absolute */
|
||||
if (backup_path != NULL && !is_absolute_path(backup_path))
|
||||
elog(ERROR_ARGS, "-B, --backup-path must be an absolute path");
|
||||
if (pgdata != NULL && !is_absolute_path(pgdata))
|
||||
elog(ERROR_ARGS, "-D, --pgdata must be an absolute path");
|
||||
if (arclog_path != NULL && !is_absolute_path(arclog_path))
|
||||
@ -172,14 +186,16 @@ main(int argc, char *argv[])
|
||||
keep_arclog_files, keep_arclog_days,
|
||||
keep_srvlog_files, keep_srvlog_days,
|
||||
keep_data_generations, keep_data_days);
|
||||
else if (pg_strcasecmp(cmd, "restore") == 0)
|
||||
else if (pg_strcasecmp(cmd, "restore") == 0){
|
||||
return do_restore(target_time, target_xid, target_inclusive, target_tli);
|
||||
}
|
||||
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);
|
||||
return do_delete(&range, force);
|
||||
else
|
||||
elog(ERROR_ARGS, "invalid command \"%s\"", cmd);
|
||||
|
||||
@ -259,8 +275,12 @@ parse_range(pgBackupRange *range, const char *arg1, const char *arg2)
|
||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
|
||||
&tm.tm_hour, &tm.tm_min, &tm.tm_sec);
|
||||
|
||||
if (num < 1)
|
||||
elog(ERROR_ARGS, _("supplied id(%s) is invalid."), tmp);
|
||||
if (num < 1){
|
||||
if (strcmp(tmp,"") != 0)
|
||||
elog(ERROR_ARGS, _("supplied id(%s) is invalid."), tmp);
|
||||
else
|
||||
elog(ERROR_ARGS, _("argments are invalid. near \"%s\""), arg1);
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
|
||||
@ -269,6 +289,10 @@ parse_range(pgBackupRange *range, const char *arg1, const char *arg2)
|
||||
if (num > 1)
|
||||
tm.tm_mon -= 1;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
if(!IsValidTime(tm)){
|
||||
elog(ERROR_ARGS, _("supplied time(%s) is invalid."), arg1);
|
||||
}
|
||||
range->begin = mktime(&tm);
|
||||
|
||||
switch (num)
|
||||
|
34
pg_rman.h
34
pg_rman.h
@ -2,7 +2,7 @@
|
||||
*
|
||||
* pg_rman.h: Backup/Recovery manager for PostgreSQL.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -23,6 +23,13 @@
|
||||
#define XLOG_BLCKSZ BLCKSZ
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM < 80300
|
||||
#define TXID_CURRENT_SQL "SELECT transactionid FROM pg_locks WHERE locktype = 'transactionid' AND pid = pg_backend_pid();"
|
||||
#include <sys/stat.h>
|
||||
#else
|
||||
#define TXID_CURRENT_SQL "SELECT txid_current();"
|
||||
#endif
|
||||
|
||||
/* Directory/File names */
|
||||
#define DATABASE_DIR "database"
|
||||
#define ARCLOG_DIR "arclog"
|
||||
@ -88,6 +95,14 @@ typedef struct pgBackupRange
|
||||
#define pgBackupRangeIsSingle(range) \
|
||||
(pgBackupRangeIsValid(range) && (range)->begin == ((range)->end))
|
||||
|
||||
#define IsValidTime(tm) \
|
||||
((tm.tm_sec >= 0 && tm.tm_sec <= 60) && /* range check for tm_sec (0-60) */ \
|
||||
(tm.tm_min >= 0 && tm.tm_min <= 59) && /* range check for tm_min (0-59) */ \
|
||||
(tm.tm_hour >= 0 && tm.tm_hour <= 23) && /* range check for tm_hour(0-23) */ \
|
||||
(tm.tm_mday >= 1 && tm.tm_mday <= 31) && /* range check for tm_mday(1-31) */ \
|
||||
(tm.tm_mon >= 0 && tm.tm_mon <= 11) && /* range check for tm_mon (0-23) */ \
|
||||
(tm.tm_year + 1900 >= 1900)) /* range check for tm_year(70-) */
|
||||
|
||||
/* Backup status */
|
||||
/* XXX re-order ? */
|
||||
typedef enum BackupStatus
|
||||
@ -131,6 +146,8 @@ typedef struct pgBackup
|
||||
XLogRecPtr stop_lsn;
|
||||
time_t start_time;
|
||||
time_t end_time;
|
||||
time_t recovery_time;
|
||||
uint32 recovery_xid;
|
||||
|
||||
/* Size (-1 means not-backup'ed) */
|
||||
int64 total_data_bytes;
|
||||
@ -142,6 +159,7 @@ typedef struct pgBackup
|
||||
/* data/wal block size for compatibility check */
|
||||
uint32 block_size;
|
||||
uint32 wal_block_size;
|
||||
|
||||
} pgBackup;
|
||||
|
||||
/* special values of pgBackup */
|
||||
@ -161,6 +179,15 @@ typedef struct pgTimeLine
|
||||
XLogRecPtr end;
|
||||
} pgTimeLine;
|
||||
|
||||
typedef struct pgRecoveryTarget
|
||||
{
|
||||
bool time_specified;
|
||||
time_t recovery_target_time;
|
||||
bool xid_specified;
|
||||
unsigned int recovery_target_xid;
|
||||
bool recovery_target_inclusive;
|
||||
} pgRecoveryTarget;
|
||||
|
||||
typedef enum CompressionMode
|
||||
{
|
||||
NO_COMPRESSION,
|
||||
@ -215,12 +242,13 @@ 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);
|
||||
extern int do_delete(pgBackupRange *range, bool force);
|
||||
extern void pgBackupDelete(int keep_generations, int keep_days);
|
||||
|
||||
/* in validate.c */
|
||||
extern int do_validate(pgBackupRange *range);
|
||||
extern void pgBackupValidate(pgBackup *backup, bool size_only);
|
||||
extern void pgBackupValidate(pgBackup *backup, bool size_only, bool for_get_timeline, bool with_database);
|
||||
|
||||
/* in catalog.c */
|
||||
extern pgBackup *catalog_get_backup(time_t timestamp);
|
||||
|
@ -899,7 +899,8 @@ pgut_connect(int elevel)
|
||||
elog(ERROR_INTERRUPTED, "interrupted");
|
||||
|
||||
#ifndef PGUT_NO_PROMPT
|
||||
if (prompt_password == DEFAULT)
|
||||
// if (prompt_password == DEFAULT) // katsumata
|
||||
if (prompt_password == YES)
|
||||
prompt_for_password(username);
|
||||
#endif
|
||||
|
||||
|
2
queue.c
2
queue.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* queue.c: Job queue with thread pooling.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
112
restore.c
112
restore.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* restore.c: restore DB cluster and archived WAL.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,10 +24,14 @@ static void create_recovery_conf(const char *target_time,
|
||||
const char *target_xid,
|
||||
const char *target_inclusive,
|
||||
TimeLineID target_tli);
|
||||
static pgRecoveryTarget *checkIfCreateRecoveryConf(const char *target_time,
|
||||
const char *target_xid,
|
||||
const char *target_inclusive);
|
||||
static parray * readTimeLineHistory(TimeLineID targetTLI);
|
||||
static bool satisfy_timeline(const parray *timelines, const pgBackup *backup);
|
||||
static bool satisfy_recovery_target(const pgBackup *backup, const pgRecoveryTarget *rt);
|
||||
static TimeLineID get_current_timeline(void);
|
||||
static TimeLineID get_fullbackup_timeline(parray *backups);
|
||||
static TimeLineID get_fullbackup_timeline(parray *backups, const pgRecoveryTarget *rt);
|
||||
static void print_backup_id(const pgBackup *backup);
|
||||
static void search_next_wal(const char *path, uint32 *needId, uint32 *needSeg, parray *timelines);
|
||||
|
||||
@ -50,6 +54,7 @@ do_restore(const char *target_time,
|
||||
char timeline_dir[MAXPGPATH];
|
||||
uint32 needId = 0;
|
||||
uint32 needSeg = 0;
|
||||
pgRecoveryTarget *rt = NULL;
|
||||
|
||||
/* PGDATA and ARCLOG_PATH are always required */
|
||||
if (pgdata == NULL)
|
||||
@ -80,11 +85,19 @@ do_restore(const char *target_time,
|
||||
if (is_pg_running())
|
||||
elog(ERROR_PG_RUNNING, _("PostgreSQL server is running"));
|
||||
|
||||
rt = checkIfCreateRecoveryConf(target_time, target_xid, target_inclusive);
|
||||
if(rt == NULL){
|
||||
elog(ERROR_ARGS, _("can't create recovery.conf. specified args are invalid."));
|
||||
}
|
||||
|
||||
/* get list of backups. (index == 0) is the last backup */
|
||||
backups = catalog_get_backup_list(NULL);
|
||||
if(!backups){
|
||||
elog(ERROR_SYSTEM, _("can't process any more."));
|
||||
}
|
||||
|
||||
cur_tli = get_current_timeline();
|
||||
backup_tli = get_fullbackup_timeline(backups);
|
||||
backup_tli = get_fullbackup_timeline(backups, rt);
|
||||
|
||||
/* determine target timeline */
|
||||
if (target_tli == 0)
|
||||
@ -154,7 +167,7 @@ do_restore(const char *target_time,
|
||||
_("can't restore from compressed backup (compression not supported in this installation)"));
|
||||
}
|
||||
#endif
|
||||
if (satisfy_timeline(timelines, base_backup))
|
||||
if (satisfy_timeline(timelines, base_backup) && satisfy_recovery_target(base_backup, rt))
|
||||
goto base_backup_found;
|
||||
}
|
||||
/* no full backup found, can't restore */
|
||||
@ -168,6 +181,7 @@ base_backup_found:
|
||||
|
||||
/* restore base backup */
|
||||
restore_database(base_backup);
|
||||
|
||||
last_restored_index = base_index;
|
||||
|
||||
/* restore following incremental backup */
|
||||
@ -183,11 +197,11 @@ base_backup_found:
|
||||
continue;
|
||||
|
||||
/* use database backup only */
|
||||
if (backup->backup_mode < BACKUP_MODE_INCREMENTAL)
|
||||
if (backup->backup_mode != BACKUP_MODE_INCREMENTAL)
|
||||
continue;
|
||||
|
||||
/* is the backup is necessary for restore to target timeline ? */
|
||||
if (!satisfy_timeline(timelines, backup))
|
||||
if (!satisfy_timeline(timelines, backup) && !satisfy_recovery_target(backup, rt))
|
||||
continue;
|
||||
|
||||
if (verbose)
|
||||
@ -314,9 +328,9 @@ restore_database(pgBackup *backup)
|
||||
|
||||
/*
|
||||
* Validate backup files with its size, because load of CRC calculation is
|
||||
* not light.
|
||||
* not right.
|
||||
*/
|
||||
pgBackupValidate(backup, true);
|
||||
pgBackupValidate(backup, true, false, true);
|
||||
|
||||
/* make direcotries and symbolic links */
|
||||
pgBackupGetPath(backup, path, lengthof(path), MKDIRS_SH_FILE);
|
||||
@ -452,7 +466,7 @@ restore_database(pgBackup *backup)
|
||||
parray_free(files);
|
||||
|
||||
if (verbose && !check)
|
||||
printf(_("resotre backup completed\n"));
|
||||
printf(_("restore backup completed\n"));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -476,6 +490,12 @@ restore_archive_logs(pgBackup *backup)
|
||||
printf(_("restoring WAL from backup %s.\n"), timestamp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate backup files with its size, because load of CRC calculation is
|
||||
* not light.
|
||||
*/
|
||||
pgBackupValidate(backup, true, false, false);
|
||||
|
||||
pgBackupGetPath(backup, list_path, lengthof(list_path), ARCLOG_FILE_LIST);
|
||||
pgBackupGetPath(backup, base_path, lengthof(list_path), ARCLOG_DIR);
|
||||
files = dir_read_file_list(base_path, list_path);
|
||||
@ -806,6 +826,28 @@ readTimeLineHistory(TimeLineID targetTLI)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
satisfy_recovery_target(const pgBackup *backup, const pgRecoveryTarget *rt)
|
||||
{
|
||||
if(rt->xid_specified){
|
||||
// elog(INFO, "in satisfy_recovery_target:xid::%u:%u", backup->recovery_xid, rt->recovery_target_xid);
|
||||
if(backup->recovery_xid <= rt->recovery_target_xid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if(rt->time_specified){
|
||||
// elog(INFO, "in satisfy_recovery_target:time_t::%ld:%ld", backup->recovery_time, rt->recovery_target_time);
|
||||
if(backup->recovery_time <= rt->recovery_target_time)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
satisfy_timeline(const parray *timelines, const pgBackup *backup)
|
||||
{
|
||||
@ -878,7 +920,7 @@ get_current_timeline(void)
|
||||
|
||||
/* get TLI of the latest full backup */
|
||||
static TimeLineID
|
||||
get_fullbackup_timeline(parray *backups)
|
||||
get_fullbackup_timeline(parray *backups, const pgRecoveryTarget *rt)
|
||||
{
|
||||
int i;
|
||||
pgBackup *base_backup = NULL;
|
||||
@ -892,10 +934,13 @@ get_fullbackup_timeline(parray *backups)
|
||||
{
|
||||
/*
|
||||
* Validate backup files with its size, because load of CRC
|
||||
* calculation is not light.
|
||||
* calculation is not right.
|
||||
*/
|
||||
if (base_backup->status == BACKUP_STATUS_DONE)
|
||||
pgBackupValidate(base_backup, true);
|
||||
pgBackupValidate(base_backup, true, true, false);
|
||||
|
||||
if(!satisfy_recovery_target(base_backup, rt))
|
||||
continue;
|
||||
|
||||
if (base_backup->status == BACKUP_STATUS_OK)
|
||||
break;
|
||||
@ -969,3 +1014,46 @@ search_next_wal(const char *path, uint32 *needId, uint32 *needSeg, parray *timel
|
||||
NextLogSeg(*needId, *needSeg);
|
||||
}
|
||||
}
|
||||
|
||||
static pgRecoveryTarget *
|
||||
checkIfCreateRecoveryConf(const char *target_time,
|
||||
const char *target_xid,
|
||||
const char *target_inclusive)
|
||||
{
|
||||
time_t dummy_time;
|
||||
unsigned int dummy_xid;
|
||||
bool dummy_bool;
|
||||
pgRecoveryTarget *rt;
|
||||
|
||||
// init pgRecoveryTarget
|
||||
rt = pgut_new(pgRecoveryTarget);
|
||||
rt->time_specified = false;
|
||||
rt->xid_specified = false;
|
||||
rt->recovery_target_time = 0;
|
||||
rt->recovery_target_xid = 0;
|
||||
rt->recovery_target_inclusive = false;
|
||||
|
||||
if(target_time){
|
||||
rt->time_specified = true;
|
||||
if(parse_time(target_time, &dummy_time))
|
||||
rt->recovery_target_time = dummy_time;
|
||||
else
|
||||
elog(ERROR_ARGS, _("can't create recovery.conf with %s"), target_time);
|
||||
}
|
||||
if(target_xid){
|
||||
rt->xid_specified = true;
|
||||
if(parse_uint32(target_xid, &dummy_xid))
|
||||
rt->recovery_target_xid = dummy_xid;
|
||||
else
|
||||
elog(ERROR_ARGS, _("can't create recovery.conf with %s"), target_xid);
|
||||
}
|
||||
if(target_inclusive){
|
||||
if(parse_bool(target_inclusive, &dummy_bool))
|
||||
rt->recovery_target_inclusive = dummy_bool;
|
||||
else
|
||||
elog(ERROR_ARGS, _("can't create recovery.conf with %s"), target_inclusive);
|
||||
}
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
7
show.c
7
show.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* show.c: show backup catalog.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -45,8 +45,9 @@ do_show(pgBackupRange *range, bool show_timeline, bool show_all)
|
||||
parray *backup_list;
|
||||
|
||||
backup_list = catalog_get_backup_list(range);
|
||||
if (backup_list == NULL)
|
||||
return 1;
|
||||
if (backup_list == NULL){
|
||||
elog(ERROR_SYSTEM, _("can't process any more."));
|
||||
}
|
||||
|
||||
if (!show_timeline)
|
||||
show_backup_list(stdout, backup_list, show_all);
|
||||
|
@ -75,6 +75,7 @@ initdb --no-locale > $BASE_PATH/results/initdb.log 2>&1
|
||||
cat << EOF >> $PGDATA/postgresql.conf
|
||||
port = $TEST_PGPORT
|
||||
logging_collector = on
|
||||
wal_level = archive
|
||||
archive_mode = on
|
||||
archive_command = 'cp "%p" "$ARCLOG_PATH/%f"'
|
||||
EOF
|
||||
@ -113,7 +114,8 @@ EOF
|
||||
export KEEP_DATA_GENERATIONS=2
|
||||
export KEEP_DATA_DAYS=0
|
||||
for i in `seq 1 5`; do
|
||||
pg_rman -p $TEST_PGPORT backup --verbose -d postgres > $BASE_PATH/results/log_full_0_$i 2>&1
|
||||
# pg_rman -p $TEST_PGPORT backup --verbose -d postgres > $BASE_PATH/results/log_full_0_$i 2>&1
|
||||
pg_rman -w -p $TEST_PGPORT backup --verbose -d postgres > $BASE_PATH/results/log_full_0_$i 2>&1
|
||||
done
|
||||
pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show_d_1 2>&1
|
||||
echo "# of deleted backups"
|
||||
@ -123,12 +125,14 @@ pgbench -p $TEST_PGPORT -i -s $SCALE pgbench > $BASE_PATH/results/pgbench.log 2>
|
||||
|
||||
echo "full database backup"
|
||||
psql -p $TEST_PGPORT postgres -c "checkpoint"
|
||||
pg_rman -p $TEST_PGPORT backup --verbose -d postgres > $BASE_PATH/results/log_full_1 2>&1
|
||||
#pg_rman -p $TEST_PGPORT backup --verbose -d postgres > $BASE_PATH/results/log_full_1 2>&1
|
||||
pg_rman -w -p $TEST_PGPORT backup --verbose -d postgres > $BASE_PATH/results/log_full_1 2>&1
|
||||
|
||||
pgbench -p $TEST_PGPORT -T $DURATION -c 10 pgbench >> $BASE_PATH/results/pgbench.log 2>&1
|
||||
echo "incremental database backup"
|
||||
psql -p $TEST_PGPORT postgres -c "checkpoint"
|
||||
pg_rman -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/results/log_incr1 2>&1
|
||||
#pg_rman -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/results/log_incr1 2>&1
|
||||
pg_rman -w -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/results/log_incr1 2>&1
|
||||
|
||||
# validate all backup
|
||||
pg_rman validate `date +%Y` --verbose > $BASE_PATH/results/log_validate1 2>&1
|
||||
@ -136,11 +140,13 @@ pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/re
|
||||
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
|
||||
#pg_rman -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/results/log_incr2 2>&1
|
||||
pg_rman -w -p $TEST_PGPORT backup -b i --verbose -d postgres > $BASE_PATH/results/log_incr2 2>&1
|
||||
|
||||
pgbench -p $TEST_PGPORT -T $DURATION -c 10 pgbench >> $BASE_PATH/results/pgbench.log 2>&1
|
||||
echo "archived WAL and serverlog backup"
|
||||
pg_rman -p $TEST_PGPORT backup -b a --verbose -d postgres > $BASE_PATH/results/log_arclog 2>&1
|
||||
#pg_rman -p $TEST_PGPORT backup -b a --verbose -d postgres > $BASE_PATH/results/log_arclog 2>&1
|
||||
pg_rman -w -p $TEST_PGPORT backup -b a --verbose -d postgres > $BASE_PATH/results/log_arclog 2>&1
|
||||
|
||||
# stop PG during transaction and get commited info for verifing
|
||||
echo "stop DB during running pgbench"
|
||||
@ -211,7 +217,8 @@ diff $BASE_PATH/results/dump_before.sql $BASE_PATH/results/dump_after.sql
|
||||
# incrementa backup can't find last full backup because new timeline started.
|
||||
echo "full database backup after recovery"
|
||||
psql -p $TEST_PGPORT postgres -c "checkpoint"
|
||||
pg_rman -p $TEST_PGPORT backup -b f --verbose -d postgres > $BASE_PATH/results/log_full2 2>&1
|
||||
#pg_rman -p $TEST_PGPORT backup -b f --verbose -d postgres > $BASE_PATH/results/log_full2 2>&1
|
||||
pg_rman -w -p $TEST_PGPORT backup -b f --verbose -d postgres > $BASE_PATH/results/log_full2 2>&1
|
||||
|
||||
# Backup of online-WAL should been deleted, but serverlog remain.
|
||||
echo "# of files in BACKUP_PATH/backup/pg_xlog"
|
||||
|
@ -1,4 +1,4 @@
|
||||
\! rm -rf results/init_test
|
||||
\! pg_rman init -B results/init_test --quiet;echo $?
|
||||
\! pg_rman init -B ${PWD}/results/init_test --quiet;echo $?
|
||||
\! find results/init_test | xargs ls -Fd | sort
|
||||
\! pg_rman init -B results/init_test --quiet;echo $?
|
||||
\! pg_rman init -B ${PWD}/results/init_test --quiet;echo $?
|
||||
|
@ -1,8 +1,8 @@
|
||||
-- test show command
|
||||
\! rm -rf results/sample_backup
|
||||
\! cp -rp data/sample_backup results/sample_backup
|
||||
\! pg_rman show -B results/sample_backup
|
||||
\! pg_rman validate -B results/sample_backup 2009-05-31 17:05:53 --debug
|
||||
\! pg_rman validate -B results/sample_backup 2009-06-01 17:05:53 --debug
|
||||
\! pg_rman show -a -B results/sample_backup
|
||||
\! pg_rman show 2009-06-01 17:05:53 -B results/sample_backup
|
||||
\! rm -rf ${PWD}/results/sample_backup
|
||||
\! cp -rp data/sample_backup ${PWD}/results/sample_backup
|
||||
\! pg_rman show -B ${PWD}/results/sample_backup
|
||||
\! pg_rman validate -B ${PWD}/results/sample_backup 2009-05-31 17:05:53 --debug
|
||||
\! pg_rman validate -B ${PWD}/results/sample_backup 2009-06-01 17:05:53 --debug
|
||||
\! pg_rman show -a -B ${PWD}/results/sample_backup
|
||||
\! pg_rman show 2009-06-01 17:05:53 -B ${PWD}/results/sample_backup
|
||||
|
2
util.c
2
util.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* util.c: log messages to log file or stderr, and misc code.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
2
utils.c
2
utils.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* utils.c:
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
123
validate.c
123
validate.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* validate.c: validate backup files.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,22 +22,36 @@ do_validate(pgBackupRange *range)
|
||||
{
|
||||
int i;
|
||||
parray *backup_list;
|
||||
int ret;
|
||||
bool another_pg_rman = false;
|
||||
|
||||
catalog_lock();
|
||||
ret = catalog_lock();
|
||||
if (ret == 1)
|
||||
another_pg_rman = true;
|
||||
|
||||
/* get backup list matches given range */
|
||||
backup_list = catalog_get_backup_list(range);
|
||||
if(!backup_list){
|
||||
elog(ERROR_SYSTEM, _("can't process any more."));
|
||||
}
|
||||
parray_qsort(backup_list, pgBackupCompareId);
|
||||
for (i = 0; i < parray_num(backup_list); i++)
|
||||
{
|
||||
pgBackup *backup = (pgBackup *)parray_get(backup_list, i);
|
||||
|
||||
/* clean extra backups (switch STATUS to ERROR) */
|
||||
if(!another_pg_rman &&
|
||||
(backup->status == BACKUP_STATUS_RUNNING || backup->status == BACKUP_STATUS_DELETING)){
|
||||
backup->status = BACKUP_STATUS_ERROR;
|
||||
pgBackupWriteIni(backup);
|
||||
}
|
||||
|
||||
/* Validate completed backups only. */
|
||||
if (backup->status != BACKUP_STATUS_DONE)
|
||||
continue;
|
||||
|
||||
/* validate with CRC value and update status to OK */
|
||||
pgBackupValidate(backup, false);
|
||||
pgBackupValidate(backup, false, false, (HAVE_DATABASE(backup)));
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
@ -53,7 +67,7 @@ do_validate(pgBackupRange *range)
|
||||
* Validate each files in the backup with its size.
|
||||
*/
|
||||
void
|
||||
pgBackupValidate(pgBackup *backup, bool size_only)
|
||||
pgBackupValidate(pgBackup *backup, bool size_only, bool for_get_timeline, bool with_database)
|
||||
{
|
||||
char timestamp[100];
|
||||
char base_path[MAXPGPATH];
|
||||
@ -62,54 +76,65 @@ pgBackupValidate(pgBackup *backup, bool size_only)
|
||||
bool corrupted = false;
|
||||
|
||||
time2iso(timestamp, lengthof(timestamp), backup->start_time);
|
||||
elog(INFO, "validate: %s", timestamp);
|
||||
|
||||
if (HAVE_DATABASE(backup))
|
||||
{
|
||||
elog(LOG, "database files...");
|
||||
pgBackupGetPath(backup, base_path, lengthof(base_path), DATABASE_DIR);
|
||||
pgBackupGetPath(backup, path, lengthof(path),
|
||||
DATABASE_FILE_LIST);
|
||||
files = dir_read_file_list(base_path, path);
|
||||
if (!pgBackupValidateFiles(files, base_path, size_only))
|
||||
corrupted = true;
|
||||
parray_walk(files, pgFileFree);
|
||||
parray_free(files);
|
||||
}
|
||||
if (HAVE_ARCLOG(backup))
|
||||
{
|
||||
elog(LOG, "archive WAL files...");
|
||||
pgBackupGetPath(backup, base_path, lengthof(base_path), ARCLOG_DIR);
|
||||
pgBackupGetPath(backup, path, lengthof(path), ARCLOG_FILE_LIST);
|
||||
files = dir_read_file_list(base_path, path);
|
||||
if (!pgBackupValidateFiles(files, base_path, size_only))
|
||||
corrupted = true;
|
||||
parray_walk(files, pgFileFree);
|
||||
parray_free(files);
|
||||
}
|
||||
if (backup->with_serverlog)
|
||||
{
|
||||
elog(LOG, "server log files...");
|
||||
pgBackupGetPath(backup, base_path, lengthof(base_path), SRVLOG_DIR);
|
||||
pgBackupGetPath(backup, path, lengthof(path), SRVLOG_FILE_LIST);
|
||||
files = dir_read_file_list(base_path, path);
|
||||
if (!pgBackupValidateFiles(files, base_path, size_only))
|
||||
corrupted = true;
|
||||
parray_walk(files, pgFileFree);
|
||||
parray_free(files);
|
||||
if(!for_get_timeline){
|
||||
if (with_database)
|
||||
elog(INFO, "validate: %s backup and archive log files by %s", timestamp, (size_only ? "SIZE" : "CRC"));
|
||||
else{
|
||||
if (backup->backup_mode == BACKUP_MODE_ARCHIVE)
|
||||
elog(INFO, "validate: %s archive log files by %s", timestamp, (size_only ? "SIZE" : "CRC"));
|
||||
else if (backup->with_serverlog)
|
||||
elog(INFO, "validate: %s server log files by %s", timestamp, (size_only ? "SIZE" : "CRC"));
|
||||
}
|
||||
}
|
||||
|
||||
/* update status to OK */
|
||||
if (corrupted)
|
||||
backup->status = BACKUP_STATUS_CORRUPT;
|
||||
else
|
||||
backup->status = BACKUP_STATUS_OK;
|
||||
pgBackupWriteIni(backup);
|
||||
if(!check){
|
||||
if (HAVE_DATABASE(backup))
|
||||
{
|
||||
elog(LOG, "database files...");
|
||||
pgBackupGetPath(backup, base_path, lengthof(base_path), DATABASE_DIR);
|
||||
pgBackupGetPath(backup, path, lengthof(path),
|
||||
DATABASE_FILE_LIST);
|
||||
files = dir_read_file_list(base_path, path);
|
||||
if (!pgBackupValidateFiles(files, base_path, size_only))
|
||||
corrupted = true;
|
||||
parray_walk(files, pgFileFree);
|
||||
parray_free(files);
|
||||
}
|
||||
if (HAVE_ARCLOG(backup))
|
||||
{
|
||||
elog(LOG, "archive WAL files...");
|
||||
pgBackupGetPath(backup, base_path, lengthof(base_path), ARCLOG_DIR);
|
||||
pgBackupGetPath(backup, path, lengthof(path), ARCLOG_FILE_LIST);
|
||||
files = dir_read_file_list(base_path, path);
|
||||
if (!pgBackupValidateFiles(files, base_path, size_only))
|
||||
corrupted = true;
|
||||
parray_walk(files, pgFileFree);
|
||||
parray_free(files);
|
||||
}
|
||||
if (backup->with_serverlog)
|
||||
{
|
||||
elog(LOG, "server log files...");
|
||||
pgBackupGetPath(backup, base_path, lengthof(base_path), SRVLOG_DIR);
|
||||
pgBackupGetPath(backup, path, lengthof(path), SRVLOG_FILE_LIST);
|
||||
files = dir_read_file_list(base_path, path);
|
||||
if (!pgBackupValidateFiles(files, base_path, size_only))
|
||||
corrupted = true;
|
||||
parray_walk(files, pgFileFree);
|
||||
parray_free(files);
|
||||
}
|
||||
|
||||
if (corrupted)
|
||||
elog(WARNING, "backup %s is corrupted", timestamp);
|
||||
else
|
||||
elog(LOG, "backup %s is valid", timestamp);
|
||||
/* update status to OK */
|
||||
if (corrupted)
|
||||
backup->status = BACKUP_STATUS_CORRUPT;
|
||||
else
|
||||
backup->status = BACKUP_STATUS_OK;
|
||||
pgBackupWriteIni(backup);
|
||||
|
||||
if (corrupted)
|
||||
elog(WARNING, "backup %s is corrupted", timestamp);
|
||||
else
|
||||
elog(LOG, "backup %s is valid", timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
2
verify.c
2
verify.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* verify.c: verify backup files.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
5
xlog.c
5
xlog.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* xlog.c: Parse WAL files.
|
||||
*
|
||||
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,6 +27,7 @@ typedef struct MemoryContextData *MemoryContext;
|
||||
#define XLOG_PAGE_MAGIC_v83 0xD062 /* 8.3 */
|
||||
#define XLOG_PAGE_MAGIC_v84 0xD063 /* 8.4 */
|
||||
#define XLOG_PAGE_MAGIC_v90 0xD064 /* 9.0 */
|
||||
#define XLOG_PAGE_MAGIC_v91 0xD066 /* 9.1 */
|
||||
|
||||
/*
|
||||
* XLogLongPageHeaderData is modified in 8.3, but the layout is compatible
|
||||
@ -75,6 +76,8 @@ xlog_is_complete_wal(const pgFile *file, int server_version)
|
||||
xlog_page_magic = XLOG_PAGE_MAGIC_v84;
|
||||
else if (server_version < 90100)
|
||||
xlog_page_magic = XLOG_PAGE_MAGIC_v90;
|
||||
else if (server_version < 90200)
|
||||
xlog_page_magic = XLOG_PAGE_MAGIC_v91;
|
||||
else
|
||||
return false; /* not supported */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user