From 78eed96f63b1067a20c4ed3577d978591875cc84 Mon Sep 17 00:00:00 2001 From: "t.katsumata1122" Date: Mon, 28 Nov 2011 04:22:05 +0000 Subject: [PATCH] revised for pg_rman1.2.2 git-svn-id: http://pg-rman.googlecode.com/svn/trunk@48 182aca00-e38e-11de-a668-6fd11605f5ce --- COPYRIGHT | 2 +- Makefile | 2 +- SPECS/pg_rman90.spec | 3 +- backup.c | 92 +- catalog.c | 18 +- clean.c | 2 +- data.c | 18 +- data/sample_backup/20090531/170553/backup.ini | 36 +- .../20090531/170553/file_database.txt | 2 +- data/sample_backup/20090601/170553/backup.ini | 36 +- .../20090601/170553/file_database.txt | 2 +- data/sample_backup/20090602/170553/backup.ini | 36 +- data/sample_backup/20090603/170553/backup.ini | 36 +- db.c | 2 +- delete.c | 38 +- dir.c | 11 +- expected/backup_restore.out | 4 +- expected/init.out | 7 +- expected/option.out | 8 +- expected/show_validate.out | 24 +- file.c | 2 +- init.c | 27 +- parray.c | 2 +- parray.h | 2 +- pg_ctl.c | 2 +- pg_rman.c | 630 +++++----- pg_rman.h | 34 +- pgsql_src/pg_crc.c | 1030 ++++++++--------- pgsql_src/pg_ctl.c | 210 ++-- pgut/pgut.c | 3 +- queue.c | 2 +- restore.c | 112 +- show.c | 7 +- sql/backup_restore.sh | 555 ++++----- sql/init.sql | 4 +- sql/option.sh | 160 +-- sql/show_validate.sql | 14 +- util.c | 2 +- utils.c | 2 +- validate.c | 123 +- verify.c | 2 +- xlog.c | 251 ++-- 42 files changed, 1940 insertions(+), 1615 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index ad2ad272..f5a68189 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -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 diff --git a/Makefile b/Makefile index 5912b18c..d6030194 100644 --- a/Makefile +++ b/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 diff --git a/SPECS/pg_rman90.spec b/SPECS/pg_rman90.spec index 00346c93..5f4855c5 100644 --- a/SPECS/pg_rman90.spec +++ b/SPECS/pg_rman90.spec @@ -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 1.2.1-1 * Wed Nov 10 2010 - NTT OSS Center 1.2.0-1 * Wed Dec 9 2009 - NTT OSS Center 1.1.1-1 - Initial cut for 1.1.1 diff --git a/backup.c b/backup.c index f8066fcf..d3b2885a 100644 --- a/backup.c +++ b/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); diff --git a/catalog.c b/catalog.c index a0b1858e..105b55dd 100644 --- a/catalog.c +++ b/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; diff --git a/clean.c b/clean.c index 3223f4c6..7d8457ae 100644 --- a/clean.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/data.c b/data.c index 786ac45c..333f32d6 100644 --- a/data.c +++ b/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); diff --git a/data/sample_backup/20090531/170553/backup.ini b/data/sample_backup/20090531/170553/backup.ini index cb7d421c..b3eba6b5 100644 --- a/data/sample_backup/20090531/170553/backup.ini +++ b/data/sample_backup/20090531/170553/backup.ini @@ -1,18 +1,18 @@ -# configuration -BACKUP_MODE=FULL -WITH_SERVERLOG=NO -COMPRESS_DATA=NO -# result -TIMELINEID=1 -START_LSN=0/0b40c800 -STOP_LSN=0/0b4c8020 -START_TIME='2009-05-31 17:05:53' -END_TIME='2009-05-31 17:09:13' -TOTAL_DATA_BYTES=1242102558 -READ_DATA_BYTES=1024 -READ_ARCLOG_BYTES=9223372036854775807 -READ_SRVLOG_BYTES=-1 -WRITE_BYTES=242102558 -BLOCK_SIZE=8192 -XLOG_BLOCK_SIZE=8192 -STATUS=DONE +# configuration +BACKUP_MODE=FULL +WITH_SERVERLOG=NO +COMPRESS_DATA=NO +# result +TIMELINEID=1 +START_LSN=0/0b40c800 +STOP_LSN=0/0b4c8020 +START_TIME='2009-05-31 17:05:53' +END_TIME='2009-05-31 17:09:13' +TOTAL_DATA_BYTES=1242102558 +READ_DATA_BYTES=1024 +READ_ARCLOG_BYTES=9223372036854775807 +READ_SRVLOG_BYTES=-1 +WRITE_BYTES=242102558 +BLOCK_SIZE=8192 +XLOG_BLOCK_SIZE=8192 +STATUS=DONE diff --git a/data/sample_backup/20090531/170553/file_database.txt b/data/sample_backup/20090531/170553/file_database.txt index d599b727..51502c4c 100644 --- a/data/sample_backup/20090531/170553/file_database.txt +++ b/data/sample_backup/20090531/170553/file_database.txt @@ -1 +1 @@ -PG_VERSION f 4 4277607361 0600 2009-08-06 18:40:18 +PG_VERSION f 4 4277607361 0600 2009-08-06 18:40:18 diff --git a/data/sample_backup/20090601/170553/backup.ini b/data/sample_backup/20090601/170553/backup.ini index fd897a9d..e5b68a2f 100644 --- a/data/sample_backup/20090601/170553/backup.ini +++ b/data/sample_backup/20090601/170553/backup.ini @@ -1,18 +1,18 @@ -# configuration -BACKUP_MODE=INCREMENTAL -WITH_SERVERLOG=NO -COMPRESS_DATA=NO -# result -TIMELINEID=1 -START_LSN=0/0b40c800 -STOP_LSN=0/0b4c8020 -START_TIME='2009-06-01 17:05:53' -END_TIME='2009-06-01 17:09:13' -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 -STATUS=DONE +# configuration +BACKUP_MODE=INCREMENTAL +WITH_SERVERLOG=NO +COMPRESS_DATA=NO +# result +TIMELINEID=1 +START_LSN=0/0b40c800 +STOP_LSN=0/0b4c8020 +START_TIME='2009-06-01 17:05:53' +END_TIME='2009-06-01 17:09:13' +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 +STATUS=DONE diff --git a/data/sample_backup/20090601/170553/file_database.txt b/data/sample_backup/20090601/170553/file_database.txt index 8a26fa01..23f5f50b 100644 --- a/data/sample_backup/20090601/170553/file_database.txt +++ b/data/sample_backup/20090601/170553/file_database.txt @@ -1 +1 @@ -PG_VERSION f 4 0 0600 2009-08-06 18:40:18 +PG_VERSION f 4 0 0600 2009-08-06 18:40:18 diff --git a/data/sample_backup/20090602/170553/backup.ini b/data/sample_backup/20090602/170553/backup.ini index 1f443111..feb14c73 100644 --- a/data/sample_backup/20090602/170553/backup.ini +++ b/data/sample_backup/20090602/170553/backup.ini @@ -1,18 +1,18 @@ -# configuration -BACKUP_MODE=ARCHIVE -WITH_SERVERLOG=YES -COMPRESS_DATA=NO -# result -TIMELINEID=1 -START_LSN=0/0b40c800 -STOP_LSN=0/0b4c8020 -START_TIME='2009-06-02 17:05:03' -END_TIME='2009-06-02 17:05:03' -TOTAL_DATA_BYTES=-1 -READ_DATA_BYTES=-1 -READ_ARCLOG_BYTES=-1 -READ_SRVLOG_BYTES=4335423 -WRITE_BYTES=162372983 -BLOCK_SIZE=8192 -XLOG_BLOCK_SIZE=8192 -STATUS=DELETED +# configuration +BACKUP_MODE=ARCHIVE +WITH_SERVERLOG=YES +COMPRESS_DATA=NO +# result +TIMELINEID=1 +START_LSN=0/0b40c800 +STOP_LSN=0/0b4c8020 +START_TIME='2009-06-02 17:05:03' +END_TIME='2009-06-02 17:05:03' +TOTAL_DATA_BYTES=-1 +READ_DATA_BYTES=-1 +READ_ARCLOG_BYTES=-1 +READ_SRVLOG_BYTES=4335423 +WRITE_BYTES=162372983 +BLOCK_SIZE=8192 +XLOG_BLOCK_SIZE=8192 +STATUS=DELETED diff --git a/data/sample_backup/20090603/170553/backup.ini b/data/sample_backup/20090603/170553/backup.ini index bfe1c908..507d7b36 100644 --- a/data/sample_backup/20090603/170553/backup.ini +++ b/data/sample_backup/20090603/170553/backup.ini @@ -1,18 +1,18 @@ -# configuration -BACKUP_MODE=FULL -WITH_SERVERLOG=YES -COMPRESS_DATA=NO -# result -TIMELINEID=1 -START_LSN=0/0b40c800 -STOP_LSN=0/0b4c8020 -START_TIME='2009-06-03 17:05:53' -END_TIME='****-**-** **:**:**' -TOTAL_DATA_BYTES=-1 -READ_DATA_BYTES=-1 -READ_ARCLOG_BYTES=-1 -READ_SRVLOG_BYTES=-1 -WRITE_BYTES=-1 -BLOCK_SIZE=8192 -XLOG_BLOCK_SIZE=8192 -STATUS=RUNNING +# configuration +BACKUP_MODE=FULL +WITH_SERVERLOG=YES +COMPRESS_DATA=NO +# result +TIMELINEID=1 +START_LSN=0/0b40c800 +STOP_LSN=0/0b4c8020 +START_TIME='2009-06-03 17:05:53' +END_TIME='2009-06-03 17:05:53' +TOTAL_DATA_BYTES=-1 +READ_DATA_BYTES=-1 +READ_ARCLOG_BYTES=-1 +READ_SRVLOG_BYTES=-1 +WRITE_BYTES=-1 +BLOCK_SIZE=8192 +XLOG_BLOCK_SIZE=8192 +STATUS=RUNNING diff --git a/db.c b/db.c index 2f26b11e..ad89577a 100644 --- a/db.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/delete.c b/delete.c index ffd1bce8..fcadf1cc 100644 --- a/delete.c +++ b/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; +} diff --git a/dir.c b/dir.c index 730979f3..85080330 100644 --- a/dir.c +++ b/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)) diff --git a/expected/backup_restore.out b/expected/backup_restore.out index aaa83b21..7c6bd7da 100644 --- a/expected/backup_restore.out +++ b/expected/backup_restore.out @@ -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 diff --git a/expected/init.out b/expected/init.out index 5d73026d..a33ab830 100644 --- a/expected/init.out +++ b/expected/init.out @@ -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 diff --git a/expected/option.out b/expected/option.out index c81506c1..ff1ce5bc 100644 --- a/expected/option.out +++ b/expected/option.out @@ -54,7 +54,7 @@ Generic options: Read the website for details. Report bugs to . -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) diff --git a/expected/show_validate.out b/expected/show_validate.out index 955db304..c7cc167f 100644 --- a/expected/show_validate.out +++ b/expected/show_validate.out @@ -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 diff --git a/file.c b/file.c index 56334146..6d4b9f28 100644 --- a/file.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/init.c b/init.c index 0755cbf4..09576e48 100644 --- a/init.c +++ b/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 +#include 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) diff --git a/parray.c b/parray.c index c317fa74..091b4d3c 100644 --- a/parray.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/parray.h b/parray.h index ca2b4af8..2e25f3b8 100644 --- a/parray.h +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/pg_ctl.c b/pg_ctl.c index 0dccec4c..a6b649d6 100644 --- a/pg_ctl.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/pg_rman.c b/pg_rman.c index dba45ce4..5e1ab757 100644 --- a/pg_rman.c +++ b/pg_rman.c @@ -1,303 +1,327 @@ -/*------------------------------------------------------------------------- - * - * pg_rman.c: Backup/Recovery manager for PostgreSQL. - * - * Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION - * - *------------------------------------------------------------------------- - */ - -#include "pg_rman.h" - -#include -#include -#include - -const char *PROGRAM_VERSION = "1.2.1"; -const char *PROGRAM_URL = "http://code.google.com/p/pg-rman/"; -const char *PROGRAM_EMAIL = "http://code.google.com/p/pg-rman/issues/list"; - -/* path configuration */ -char *backup_path; -char *pgdata; -char *arclog_path; -char *srvlog_path; - -/* common configuration */ -bool verbose = false; -bool check = false; - -/* directory configuration */ -pgBackup current; - -/* backup configuration */ -static bool smooth_checkpoint; -static int keep_arclog_files = KEEP_INFINITE; -static int keep_arclog_days = KEEP_INFINITE; -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; - -/* restore configuration */ -static char *target_time; -static char *target_xid; -static char *target_inclusive; -static TimeLineID target_tli; - -/* show configuration */ -static bool show_all = false; - -static void opt_backup_mode(pgut_option *opt, const char *arg); -static void parse_range(pgBackupRange *range, const char *arg1, const char *arg2); - -static pgut_option options[] = -{ - /* directory options */ - { 's', 'D', "pgdata" , &pgdata , SOURCE_ENV }, - { 's', 'A', "arclog-path" , &arclog_path , SOURCE_ENV }, - { 's', 'B', "backup-path" , &backup_path , SOURCE_ENV }, - { 's', 'S', "srvlog-path" , &srvlog_path , SOURCE_ENV }, - /* common options */ - { 'b', 'v', "verbose" , &verbose }, - { 'b', 'c', "check" , &check }, - /* backup options */ - { 'f', 'b', "backup-mode" , opt_backup_mode , SOURCE_ENV }, - { '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 }, - /* 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 }, - { 'i', 3, "keep-arclog-files" , &keep_arclog_files , SOURCE_ENV }, - { 'i', 4, "keep-arclog-days" , &keep_arclog_days , SOURCE_ENV }, - { 'i', 5, "keep-srvlog-files" , &keep_srvlog_files , SOURCE_ENV }, - { 'i', 6, "keep-srvlog-days" , &keep_srvlog_days , SOURCE_ENV }, - /* restore options */ - { 's', 7, "recovery-target-time" , &target_time , SOURCE_ENV }, - { '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 }, - /* catalog options */ - { 'b', 'a', "show-all" , &show_all }, - { 0 } -}; - -/* - * Entry point of pg_rman command. - */ -int -main(int argc, char *argv[]) -{ - const char *cmd = NULL; - const char *range1 = NULL; - const char *range2 = NULL; - bool show_timeline = false; - pgBackupRange range; - int i; - - /* do not buffer progress messages */ - setvbuf(stdout, 0, _IONBF, 0); /* TODO: remove this */ - - /* initialize configuration */ - catalog_init_config(¤t); - - /* overwrite configuration with command line arguments */ - i = pgut_getopt(argc, argv, options); - - for (; i < argc; i++) - { - if (cmd == NULL) - cmd = argv[i]; - else if (pg_strcasecmp(argv[i], "timeline") == 0 && - pg_strcasecmp(cmd, "show") == 0) - show_timeline = true; - else if (range1 == NULL) - range1 = argv[i]; - else if (range2 == NULL) - range2 = argv[i]; - else - elog(ERROR_ARGS, "too many arguments"); - } - - /* command argument (backup/restore/show/...) is required. */ - if (cmd == NULL) - { - help(false); - return HELP; - } - - /* get object range argument if any */ - if (range1 && range2) - parse_range(&range, range1, range2); - else if (range1) - parse_range(&range, range1, ""); - else - range.begin = range.end = 0; - - /* Read default configuration from file. */ - if (backup_path) - { - char path[MAXPGPATH]; - - join_path_components(path, backup_path, PG_RMAN_INI_FILE); - pgut_readopt(path, options, ERROR_ARGS); - } - - /* BACKUP_PATH is always required */ - if (backup_path == NULL) - elog(ERROR_ARGS, "required parameter not specified: BACKUP_PATH (-B, --backup-path)"); - - /* path must be absolute */ - 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)) - elog(ERROR_ARGS, "-A, --arclog-path must be an absolute path"); - if (srvlog_path != NULL && !is_absolute_path(srvlog_path)) - elog(ERROR_ARGS, "-S, --srvlog-path must be an absolute path"); - - /* setup exclusion list for file search */ - for (i = 0; pgdata_exclude[i]; i++) /* find first empty slot */ - ; - if (arclog_path) - pgdata_exclude[i++] = arclog_path; - if (srvlog_path) - pgdata_exclude[i++] = srvlog_path; - - /* do actual operation */ - 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); - 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); - else - elog(ERROR_ARGS, "invalid command \"%s\"", cmd); - - return 0; -} - -void -pgut_help(bool details) -{ - printf(_("%s manage backup/recovery of PostgreSQL database.\n\n"), PROGRAM_NAME); - printf(_("Usage:\n")); - printf(_(" %s OPTION init\n"), PROGRAM_NAME); - printf(_(" %s OPTION backup\n"), PROGRAM_NAME); - printf(_(" %s OPTION restore\n"), PROGRAM_NAME); - printf(_(" %s OPTION show [DATE]\n"), PROGRAM_NAME); - printf(_(" %s OPTION show timeline [DATE]\n"), PROGRAM_NAME); - printf(_(" %s OPTION validate [DATE]\n"), PROGRAM_NAME); - printf(_(" %s OPTION delete DATE\n"), PROGRAM_NAME); - - if (!details) - return; - - printf(_("\nCommon Options:\n")); - printf(_(" -D, --pgdata=PATH location of the database storage area\n")); - printf(_(" -A, --arclog-path=PATH location of archive WAL storage area\n")); - printf(_(" -S, --srvlog-path=PATH location of server log storage area\n")); - printf(_(" -B, --backup-path=PATH location of the backup storage area\n")); - printf(_(" -c, --check show what would have been done\n")); - printf(_("\nBackup options:\n")); - printf(_(" -b, --backup-mode=MODE full, incremental, or archive\n")); - printf(_(" -s, --with-serverlog also backup server log files\n")); - printf(_(" -Z, --compress-data compress data backup with zlib\n")); - printf(_(" -C, --smooth-checkpoint do smooth checkpoint before backup\n")); - printf(_(" --keep-data-generations=N keep GENERATION of full data backup\n")); - printf(_(" --keep-data-days=DAY keep enough data backup to recover to DAY days age\n")); - printf(_(" --keep-arclog-files=NUM keep NUM of archived WAL\n")); - 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(_("\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(_("\nCatalog options:\n")); - printf(_(" -a, --show-all show deleted backup too\n")); -} - -/* - * Create range object from one or two arguments. - * All not-digit characters in the argument(s) are igonred. - * Both arg1 and arg2 must be valid pointer. - */ -static void -parse_range(pgBackupRange *range, const char *arg1, const char *arg2) -{ - size_t len = strlen(arg1) + strlen(arg2) + 1; - char *tmp; - int num; - struct tm tm; - - tmp = pgut_malloc(len); - tmp[0] = '\0'; - if (arg1 != NULL) - remove_not_digit(tmp, len, arg1); - if (arg2 != NULL) - remove_not_digit(tmp + strlen(tmp), len - strlen(tmp), arg2); - - memset(&tm, 0, sizeof(tm)); - tm.tm_year = 0; /* tm_year is year - 1900 */ - tm.tm_mon = 0; /* tm_mon is 0 - 11 */ - tm.tm_mday = 1; /* tm_mday is 1 - 31 */ - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - num = sscanf(tmp, "%04d %02d %02d %02d %02d %02d", - &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); - - free(tmp); - - /* adjust year and month to convert to time_t */ - tm.tm_year -= 1900; - if (num > 1) - tm.tm_mon -= 1; - tm.tm_isdst = -1; - range->begin = mktime(&tm); - - switch (num) - { - case 1: - tm.tm_year++; - break; - case 2: - tm.tm_mon++; - break; - case 3: - tm.tm_mday++; - break; - case 4: - tm.tm_hour++; - break; - case 5: - tm.tm_min++; - break; - case 6: - tm.tm_sec++; - break; - } - range->end = mktime(&tm); - range->end--; -} - -static void -opt_backup_mode(pgut_option *opt, const char *arg) -{ - current.backup_mode = parse_backup_mode(arg, ERROR_ARGS); -} +/*------------------------------------------------------------------------- + * + * pg_rman.c: Backup/Recovery manager for PostgreSQL. + * + * Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION + * + *------------------------------------------------------------------------- + */ + +#include "pg_rman.h" + +#include +#include +#include + +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"; + +/* path configuration */ +char *backup_path; +char *pgdata; +char *arclog_path; +char *srvlog_path; + +/* common configuration */ +bool verbose = false; +bool check = false; + +/* directory configuration */ +pgBackup current; + +/* backup configuration */ +static bool smooth_checkpoint; +static int keep_arclog_files = KEEP_INFINITE; +static int keep_arclog_days = KEEP_INFINITE; +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; + +/* restore configuration */ +static char *target_time; +static char *target_xid; +static char *target_inclusive; +static TimeLineID target_tli; + +/* delete configuration */ +static bool force; + +/* show configuration */ +static bool show_all = false; + +static void opt_backup_mode(pgut_option *opt, const char *arg); +static void parse_range(pgBackupRange *range, const char *arg1, const char *arg2); + +static pgut_option options[] = +{ + /* directory options */ + { 's', 'D', "pgdata" , &pgdata , SOURCE_ENV }, + { 's', 'A', "arclog-path" , &arclog_path , SOURCE_ENV }, + { 's', 'B', "backup-path" , &backup_path , SOURCE_ENV }, + { 's', 'S', "srvlog-path" , &srvlog_path , SOURCE_ENV }, + /* common options */ + { 'b', 'v', "verbose" , &verbose }, + { 'b', 'c', "check" , &check }, + /* backup options */ + { 'f', 'b', "backup-mode" , opt_backup_mode , SOURCE_ENV }, + { '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 }, + { 'i', 3, "keep-arclog-files" , &keep_arclog_files , SOURCE_ENV }, + { 'i', 4, "keep-arclog-days" , &keep_arclog_days , SOURCE_ENV }, + { 'i', 5, "keep-srvlog-files" , &keep_srvlog_files , SOURCE_ENV }, + { 'i', 6, "keep-srvlog-days" , &keep_srvlog_days , SOURCE_ENV }, + /* restore options */ + { 's', 7, "recovery-target-time" , &target_time , SOURCE_ENV }, + { '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 }, + /* catalog options */ + { 'b', 'a', "show-all" , &show_all }, + { 0 } +}; + +/* + * Entry point of pg_rman command. + */ +int +main(int argc, char *argv[]) +{ + const char *cmd = NULL; + const char *range1 = NULL; + const char *range2 = NULL; + bool show_timeline = false; + pgBackupRange range; + int i; + + /* do not buffer progress messages */ + setvbuf(stdout, 0, _IONBF, 0); /* TODO: remove this */ + + /* initialize configuration */ + catalog_init_config(¤t); + + /* overwrite configuration with command line arguments */ + i = pgut_getopt(argc, argv, options); + + for (; i < argc; i++) + { + if (cmd == NULL) + cmd = argv[i]; + else if (pg_strcasecmp(argv[i], "timeline") == 0 && + pg_strcasecmp(cmd, "show") == 0) + show_timeline = true; + else if (range1 == NULL) + range1 = argv[i]; + else if (range2 == NULL) + range2 = argv[i]; + else + elog(ERROR_ARGS, "too many arguments"); + } + + /* command argument (backup/restore/show/...) is required. */ + if (cmd == NULL) + { + help(false); + return HELP; + } + + /* get object range argument if any */ + if (range1 && range2) + parse_range(&range, range1, range2); + else if (range1) + parse_range(&range, range1, ""); + else + range.begin = range.end = 0; + + /* Read default configuration from file. */ + 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); + } + + /* BACKUP_PATH is always required */ + if (backup_path == NULL) + 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)) + elog(ERROR_ARGS, "-A, --arclog-path must be an absolute path"); + if (srvlog_path != NULL && !is_absolute_path(srvlog_path)) + elog(ERROR_ARGS, "-S, --srvlog-path must be an absolute path"); + + /* setup exclusion list for file search */ + for (i = 0; pgdata_exclude[i]; i++) /* find first empty slot */ + ; + if (arclog_path) + pgdata_exclude[i++] = arclog_path; + if (srvlog_path) + pgdata_exclude[i++] = srvlog_path; + + /* do actual operation */ + 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); + 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, force); + else + elog(ERROR_ARGS, "invalid command \"%s\"", cmd); + + return 0; +} + +void +pgut_help(bool details) +{ + printf(_("%s manage backup/recovery of PostgreSQL database.\n\n"), PROGRAM_NAME); + printf(_("Usage:\n")); + printf(_(" %s OPTION init\n"), PROGRAM_NAME); + printf(_(" %s OPTION backup\n"), PROGRAM_NAME); + printf(_(" %s OPTION restore\n"), PROGRAM_NAME); + printf(_(" %s OPTION show [DATE]\n"), PROGRAM_NAME); + printf(_(" %s OPTION show timeline [DATE]\n"), PROGRAM_NAME); + printf(_(" %s OPTION validate [DATE]\n"), PROGRAM_NAME); + printf(_(" %s OPTION delete DATE\n"), PROGRAM_NAME); + + if (!details) + return; + + printf(_("\nCommon Options:\n")); + printf(_(" -D, --pgdata=PATH location of the database storage area\n")); + printf(_(" -A, --arclog-path=PATH location of archive WAL storage area\n")); + printf(_(" -S, --srvlog-path=PATH location of server log storage area\n")); + printf(_(" -B, --backup-path=PATH location of the backup storage area\n")); + printf(_(" -c, --check show what would have been done\n")); + printf(_("\nBackup options:\n")); + printf(_(" -b, --backup-mode=MODE full, incremental, or archive\n")); + printf(_(" -s, --with-serverlog also backup server log files\n")); + printf(_(" -Z, --compress-data compress data backup with zlib\n")); + printf(_(" -C, --smooth-checkpoint do smooth checkpoint before backup\n")); + printf(_(" --keep-data-generations=N keep GENERATION of full data backup\n")); + printf(_(" --keep-data-days=DAY keep enough data backup to recover to DAY days age\n")); + printf(_(" --keep-arclog-files=NUM keep NUM of archived WAL\n")); + 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(_("\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(_("\nCatalog options:\n")); + printf(_(" -a, --show-all show deleted backup too\n")); +} + +/* + * Create range object from one or two arguments. + * All not-digit characters in the argument(s) are igonred. + * Both arg1 and arg2 must be valid pointer. + */ +static void +parse_range(pgBackupRange *range, const char *arg1, const char *arg2) +{ + size_t len = strlen(arg1) + strlen(arg2) + 1; + char *tmp; + int num; + struct tm tm; + + tmp = pgut_malloc(len); + tmp[0] = '\0'; + if (arg1 != NULL) + remove_not_digit(tmp, len, arg1); + if (arg2 != NULL) + remove_not_digit(tmp + strlen(tmp), len - strlen(tmp), arg2); + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = 0; /* tm_year is year - 1900 */ + tm.tm_mon = 0; /* tm_mon is 0 - 11 */ + tm.tm_mday = 1; /* tm_mday is 1 - 31 */ + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + num = sscanf(tmp, "%04d %02d %02d %02d %02d %02d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec); + + 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); + + /* adjust year and month to convert to time_t */ + tm.tm_year -= 1900; + 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) + { + case 1: + tm.tm_year++; + break; + case 2: + tm.tm_mon++; + break; + case 3: + tm.tm_mday++; + break; + case 4: + tm.tm_hour++; + break; + case 5: + tm.tm_min++; + break; + case 6: + tm.tm_sec++; + break; + } + range->end = mktime(&tm); + range->end--; +} + +static void +opt_backup_mode(pgut_option *opt, const char *arg) +{ + current.backup_mode = parse_backup_mode(arg, ERROR_ARGS); +} diff --git a/pg_rman.h b/pg_rman.h index ea3644c5..0e77caef 100644 --- a/pg_rman.h +++ b/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 +#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); diff --git a/pgsql_src/pg_crc.c b/pgsql_src/pg_crc.c index c4ba3deb..f7d7220d 100644 --- a/pgsql_src/pg_crc.c +++ b/pgsql_src/pg_crc.c @@ -1,515 +1,515 @@ -/*------------------------------------------------------------------------- - * - * pg_crc.c - * PostgreSQL CRC support - * - * See Ross Williams' excellent introduction - * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from - * http://www.ross.net/crc/download/crc_v3.txt or several other net sites. - * - * We use a normal (not "reflected", in Williams' terms) CRC, using initial - * all-ones register contents and a final bit inversion. - * - * The 64-bit variant is not used as of PostgreSQL 8.1, but we retain the - * code for possible future use. - * - * - * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/hash/pg_crc.c,v 1.21 2009/01/01 17:23:51 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -/* Use c.h so that this file can be built in either frontend or backend */ -#include "c.h" - - -/* - * This table is based on the polynomial - * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - * (This is the same polynomial used in Ethernet checksums, for instance.) - */ -const uint32 pg_crc32_table[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -}; - - -#ifdef PROVIDE_64BIT_CRC - -/* - * This table is based on the polynomial - * - * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 + - * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 + - * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 + - * x^7 + x^4 + x + 1 - * - * which is borrowed from the DLT1 spec - * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM) - */ - -#ifdef INT64_IS_BUSTED - -const uint32 pg_crc64_table0[256] = { - 0x00000000, 0xA9EA3693, - 0x53D46D26, 0xFA3E5BB5, - 0x0E42ECDF, 0xA7A8DA4C, - 0x5D9681F9, 0xF47CB76A, - 0x1C85D9BE, 0xB56FEF2D, - 0x4F51B498, 0xE6BB820B, - 0x12C73561, 0xBB2D03F2, - 0x41135847, 0xE8F96ED4, - 0x90E185EF, 0x390BB37C, - 0xC335E8C9, 0x6ADFDE5A, - 0x9EA36930, 0x37495FA3, - 0xCD770416, 0x649D3285, - 0x8C645C51, 0x258E6AC2, - 0xDFB03177, 0x765A07E4, - 0x8226B08E, 0x2BCC861D, - 0xD1F2DDA8, 0x7818EB3B, - 0x21C30BDE, 0x88293D4D, - 0x721766F8, 0xDBFD506B, - 0x2F81E701, 0x866BD192, - 0x7C558A27, 0xD5BFBCB4, - 0x3D46D260, 0x94ACE4F3, - 0x6E92BF46, 0xC77889D5, - 0x33043EBF, 0x9AEE082C, - 0x60D05399, 0xC93A650A, - 0xB1228E31, 0x18C8B8A2, - 0xE2F6E317, 0x4B1CD584, - 0xBF6062EE, 0x168A547D, - 0xECB40FC8, 0x455E395B, - 0xADA7578F, 0x044D611C, - 0xFE733AA9, 0x57990C3A, - 0xA3E5BB50, 0x0A0F8DC3, - 0xF031D676, 0x59DBE0E5, - 0xEA6C212F, 0x438617BC, - 0xB9B84C09, 0x10527A9A, - 0xE42ECDF0, 0x4DC4FB63, - 0xB7FAA0D6, 0x1E109645, - 0xF6E9F891, 0x5F03CE02, - 0xA53D95B7, 0x0CD7A324, - 0xF8AB144E, 0x514122DD, - 0xAB7F7968, 0x02954FFB, - 0x7A8DA4C0, 0xD3679253, - 0x2959C9E6, 0x80B3FF75, - 0x74CF481F, 0xDD257E8C, - 0x271B2539, 0x8EF113AA, - 0x66087D7E, 0xCFE24BED, - 0x35DC1058, 0x9C3626CB, - 0x684A91A1, 0xC1A0A732, - 0x3B9EFC87, 0x9274CA14, - 0xCBAF2AF1, 0x62451C62, - 0x987B47D7, 0x31917144, - 0xC5EDC62E, 0x6C07F0BD, - 0x9639AB08, 0x3FD39D9B, - 0xD72AF34F, 0x7EC0C5DC, - 0x84FE9E69, 0x2D14A8FA, - 0xD9681F90, 0x70822903, - 0x8ABC72B6, 0x23564425, - 0x5B4EAF1E, 0xF2A4998D, - 0x089AC238, 0xA170F4AB, - 0x550C43C1, 0xFCE67552, - 0x06D82EE7, 0xAF321874, - 0x47CB76A0, 0xEE214033, - 0x141F1B86, 0xBDF52D15, - 0x49899A7F, 0xE063ACEC, - 0x1A5DF759, 0xB3B7C1CA, - 0x7D3274CD, 0xD4D8425E, - 0x2EE619EB, 0x870C2F78, - 0x73709812, 0xDA9AAE81, - 0x20A4F534, 0x894EC3A7, - 0x61B7AD73, 0xC85D9BE0, - 0x3263C055, 0x9B89F6C6, - 0x6FF541AC, 0xC61F773F, - 0x3C212C8A, 0x95CB1A19, - 0xEDD3F122, 0x4439C7B1, - 0xBE079C04, 0x17EDAA97, - 0xE3911DFD, 0x4A7B2B6E, - 0xB04570DB, 0x19AF4648, - 0xF156289C, 0x58BC1E0F, - 0xA28245BA, 0x0B687329, - 0xFF14C443, 0x56FEF2D0, - 0xACC0A965, 0x052A9FF6, - 0x5CF17F13, 0xF51B4980, - 0x0F251235, 0xA6CF24A6, - 0x52B393CC, 0xFB59A55F, - 0x0167FEEA, 0xA88DC879, - 0x4074A6AD, 0xE99E903E, - 0x13A0CB8B, 0xBA4AFD18, - 0x4E364A72, 0xE7DC7CE1, - 0x1DE22754, 0xB40811C7, - 0xCC10FAFC, 0x65FACC6F, - 0x9FC497DA, 0x362EA149, - 0xC2521623, 0x6BB820B0, - 0x91867B05, 0x386C4D96, - 0xD0952342, 0x797F15D1, - 0x83414E64, 0x2AAB78F7, - 0xDED7CF9D, 0x773DF90E, - 0x8D03A2BB, 0x24E99428, - 0x975E55E2, 0x3EB46371, - 0xC48A38C4, 0x6D600E57, - 0x991CB93D, 0x30F68FAE, - 0xCAC8D41B, 0x6322E288, - 0x8BDB8C5C, 0x2231BACF, - 0xD80FE17A, 0x71E5D7E9, - 0x85996083, 0x2C735610, - 0xD64D0DA5, 0x7FA73B36, - 0x07BFD00D, 0xAE55E69E, - 0x546BBD2B, 0xFD818BB8, - 0x09FD3CD2, 0xA0170A41, - 0x5A2951F4, 0xF3C36767, - 0x1B3A09B3, 0xB2D03F20, - 0x48EE6495, 0xE1045206, - 0x1578E56C, 0xBC92D3FF, - 0x46AC884A, 0xEF46BED9, - 0xB69D5E3C, 0x1F7768AF, - 0xE549331A, 0x4CA30589, - 0xB8DFB2E3, 0x11358470, - 0xEB0BDFC5, 0x42E1E956, - 0xAA188782, 0x03F2B111, - 0xF9CCEAA4, 0x5026DC37, - 0xA45A6B5D, 0x0DB05DCE, - 0xF78E067B, 0x5E6430E8, - 0x267CDBD3, 0x8F96ED40, - 0x75A8B6F5, 0xDC428066, - 0x283E370C, 0x81D4019F, - 0x7BEA5A2A, 0xD2006CB9, - 0x3AF9026D, 0x931334FE, - 0x692D6F4B, 0xC0C759D8, - 0x34BBEEB2, 0x9D51D821, - 0x676F8394, 0xCE85B507 -}; - -const uint32 pg_crc64_table1[256] = { - 0x00000000, 0x42F0E1EB, - 0x85E1C3D7, 0xC711223C, - 0x49336645, 0x0BC387AE, - 0xCCD2A592, 0x8E224479, - 0x9266CC8A, 0xD0962D61, - 0x17870F5D, 0x5577EEB6, - 0xDB55AACF, 0x99A54B24, - 0x5EB46918, 0x1C4488F3, - 0x663D78FF, 0x24CD9914, - 0xE3DCBB28, 0xA12C5AC3, - 0x2F0E1EBA, 0x6DFEFF51, - 0xAAEFDD6D, 0xE81F3C86, - 0xF45BB475, 0xB6AB559E, - 0x71BA77A2, 0x334A9649, - 0xBD68D230, 0xFF9833DB, - 0x388911E7, 0x7A79F00C, - 0xCC7AF1FF, 0x8E8A1014, - 0x499B3228, 0x0B6BD3C3, - 0x854997BA, 0xC7B97651, - 0x00A8546D, 0x4258B586, - 0x5E1C3D75, 0x1CECDC9E, - 0xDBFDFEA2, 0x990D1F49, - 0x172F5B30, 0x55DFBADB, - 0x92CE98E7, 0xD03E790C, - 0xAA478900, 0xE8B768EB, - 0x2FA64AD7, 0x6D56AB3C, - 0xE374EF45, 0xA1840EAE, - 0x66952C92, 0x2465CD79, - 0x3821458A, 0x7AD1A461, - 0xBDC0865D, 0xFF3067B6, - 0x711223CF, 0x33E2C224, - 0xF4F3E018, 0xB60301F3, - 0xDA050215, 0x98F5E3FE, - 0x5FE4C1C2, 0x1D142029, - 0x93366450, 0xD1C685BB, - 0x16D7A787, 0x5427466C, - 0x4863CE9F, 0x0A932F74, - 0xCD820D48, 0x8F72ECA3, - 0x0150A8DA, 0x43A04931, - 0x84B16B0D, 0xC6418AE6, - 0xBC387AEA, 0xFEC89B01, - 0x39D9B93D, 0x7B2958D6, - 0xF50B1CAF, 0xB7FBFD44, - 0x70EADF78, 0x321A3E93, - 0x2E5EB660, 0x6CAE578B, - 0xABBF75B7, 0xE94F945C, - 0x676DD025, 0x259D31CE, - 0xE28C13F2, 0xA07CF219, - 0x167FF3EA, 0x548F1201, - 0x939E303D, 0xD16ED1D6, - 0x5F4C95AF, 0x1DBC7444, - 0xDAAD5678, 0x985DB793, - 0x84193F60, 0xC6E9DE8B, - 0x01F8FCB7, 0x43081D5C, - 0xCD2A5925, 0x8FDAB8CE, - 0x48CB9AF2, 0x0A3B7B19, - 0x70428B15, 0x32B26AFE, - 0xF5A348C2, 0xB753A929, - 0x3971ED50, 0x7B810CBB, - 0xBC902E87, 0xFE60CF6C, - 0xE224479F, 0xA0D4A674, - 0x67C58448, 0x253565A3, - 0xAB1721DA, 0xE9E7C031, - 0x2EF6E20D, 0x6C0603E6, - 0xF6FAE5C0, 0xB40A042B, - 0x731B2617, 0x31EBC7FC, - 0xBFC98385, 0xFD39626E, - 0x3A284052, 0x78D8A1B9, - 0x649C294A, 0x266CC8A1, - 0xE17DEA9D, 0xA38D0B76, - 0x2DAF4F0F, 0x6F5FAEE4, - 0xA84E8CD8, 0xEABE6D33, - 0x90C79D3F, 0xD2377CD4, - 0x15265EE8, 0x57D6BF03, - 0xD9F4FB7A, 0x9B041A91, - 0x5C1538AD, 0x1EE5D946, - 0x02A151B5, 0x4051B05E, - 0x87409262, 0xC5B07389, - 0x4B9237F0, 0x0962D61B, - 0xCE73F427, 0x8C8315CC, - 0x3A80143F, 0x7870F5D4, - 0xBF61D7E8, 0xFD913603, - 0x73B3727A, 0x31439391, - 0xF652B1AD, 0xB4A25046, - 0xA8E6D8B5, 0xEA16395E, - 0x2D071B62, 0x6FF7FA89, - 0xE1D5BEF0, 0xA3255F1B, - 0x64347D27, 0x26C49CCC, - 0x5CBD6CC0, 0x1E4D8D2B, - 0xD95CAF17, 0x9BAC4EFC, - 0x158E0A85, 0x577EEB6E, - 0x906FC952, 0xD29F28B9, - 0xCEDBA04A, 0x8C2B41A1, - 0x4B3A639D, 0x09CA8276, - 0x87E8C60F, 0xC51827E4, - 0x020905D8, 0x40F9E433, - 0x2CFFE7D5, 0x6E0F063E, - 0xA91E2402, 0xEBEEC5E9, - 0x65CC8190, 0x273C607B, - 0xE02D4247, 0xA2DDA3AC, - 0xBE992B5F, 0xFC69CAB4, - 0x3B78E888, 0x79880963, - 0xF7AA4D1A, 0xB55AACF1, - 0x724B8ECD, 0x30BB6F26, - 0x4AC29F2A, 0x08327EC1, - 0xCF235CFD, 0x8DD3BD16, - 0x03F1F96F, 0x41011884, - 0x86103AB8, 0xC4E0DB53, - 0xD8A453A0, 0x9A54B24B, - 0x5D459077, 0x1FB5719C, - 0x919735E5, 0xD367D40E, - 0x1476F632, 0x568617D9, - 0xE085162A, 0xA275F7C1, - 0x6564D5FD, 0x27943416, - 0xA9B6706F, 0xEB469184, - 0x2C57B3B8, 0x6EA75253, - 0x72E3DAA0, 0x30133B4B, - 0xF7021977, 0xB5F2F89C, - 0x3BD0BCE5, 0x79205D0E, - 0xBE317F32, 0xFCC19ED9, - 0x86B86ED5, 0xC4488F3E, - 0x0359AD02, 0x41A94CE9, - 0xCF8B0890, 0x8D7BE97B, - 0x4A6ACB47, 0x089A2AAC, - 0x14DEA25F, 0x562E43B4, - 0x913F6188, 0xD3CF8063, - 0x5DEDC41A, 0x1F1D25F1, - 0xD80C07CD, 0x9AFCE626 -}; -#else /* int64 works */ - -const uint64 pg_crc64_table[256] = { - UINT64CONST(0x0000000000000000), UINT64CONST(0x42F0E1EBA9EA3693), - UINT64CONST(0x85E1C3D753D46D26), UINT64CONST(0xC711223CFA3E5BB5), - UINT64CONST(0x493366450E42ECDF), UINT64CONST(0x0BC387AEA7A8DA4C), - UINT64CONST(0xCCD2A5925D9681F9), UINT64CONST(0x8E224479F47CB76A), - UINT64CONST(0x9266CC8A1C85D9BE), UINT64CONST(0xD0962D61B56FEF2D), - UINT64CONST(0x17870F5D4F51B498), UINT64CONST(0x5577EEB6E6BB820B), - UINT64CONST(0xDB55AACF12C73561), UINT64CONST(0x99A54B24BB2D03F2), - UINT64CONST(0x5EB4691841135847), UINT64CONST(0x1C4488F3E8F96ED4), - UINT64CONST(0x663D78FF90E185EF), UINT64CONST(0x24CD9914390BB37C), - UINT64CONST(0xE3DCBB28C335E8C9), UINT64CONST(0xA12C5AC36ADFDE5A), - UINT64CONST(0x2F0E1EBA9EA36930), UINT64CONST(0x6DFEFF5137495FA3), - UINT64CONST(0xAAEFDD6DCD770416), UINT64CONST(0xE81F3C86649D3285), - UINT64CONST(0xF45BB4758C645C51), UINT64CONST(0xB6AB559E258E6AC2), - UINT64CONST(0x71BA77A2DFB03177), UINT64CONST(0x334A9649765A07E4), - UINT64CONST(0xBD68D2308226B08E), UINT64CONST(0xFF9833DB2BCC861D), - UINT64CONST(0x388911E7D1F2DDA8), UINT64CONST(0x7A79F00C7818EB3B), - UINT64CONST(0xCC7AF1FF21C30BDE), UINT64CONST(0x8E8A101488293D4D), - UINT64CONST(0x499B3228721766F8), UINT64CONST(0x0B6BD3C3DBFD506B), - UINT64CONST(0x854997BA2F81E701), UINT64CONST(0xC7B97651866BD192), - UINT64CONST(0x00A8546D7C558A27), UINT64CONST(0x4258B586D5BFBCB4), - UINT64CONST(0x5E1C3D753D46D260), UINT64CONST(0x1CECDC9E94ACE4F3), - UINT64CONST(0xDBFDFEA26E92BF46), UINT64CONST(0x990D1F49C77889D5), - UINT64CONST(0x172F5B3033043EBF), UINT64CONST(0x55DFBADB9AEE082C), - UINT64CONST(0x92CE98E760D05399), UINT64CONST(0xD03E790CC93A650A), - UINT64CONST(0xAA478900B1228E31), UINT64CONST(0xE8B768EB18C8B8A2), - UINT64CONST(0x2FA64AD7E2F6E317), UINT64CONST(0x6D56AB3C4B1CD584), - UINT64CONST(0xE374EF45BF6062EE), UINT64CONST(0xA1840EAE168A547D), - UINT64CONST(0x66952C92ECB40FC8), UINT64CONST(0x2465CD79455E395B), - UINT64CONST(0x3821458AADA7578F), UINT64CONST(0x7AD1A461044D611C), - UINT64CONST(0xBDC0865DFE733AA9), UINT64CONST(0xFF3067B657990C3A), - UINT64CONST(0x711223CFA3E5BB50), UINT64CONST(0x33E2C2240A0F8DC3), - UINT64CONST(0xF4F3E018F031D676), UINT64CONST(0xB60301F359DBE0E5), - UINT64CONST(0xDA050215EA6C212F), UINT64CONST(0x98F5E3FE438617BC), - UINT64CONST(0x5FE4C1C2B9B84C09), UINT64CONST(0x1D14202910527A9A), - UINT64CONST(0x93366450E42ECDF0), UINT64CONST(0xD1C685BB4DC4FB63), - UINT64CONST(0x16D7A787B7FAA0D6), UINT64CONST(0x5427466C1E109645), - UINT64CONST(0x4863CE9FF6E9F891), UINT64CONST(0x0A932F745F03CE02), - UINT64CONST(0xCD820D48A53D95B7), UINT64CONST(0x8F72ECA30CD7A324), - UINT64CONST(0x0150A8DAF8AB144E), UINT64CONST(0x43A04931514122DD), - UINT64CONST(0x84B16B0DAB7F7968), UINT64CONST(0xC6418AE602954FFB), - UINT64CONST(0xBC387AEA7A8DA4C0), UINT64CONST(0xFEC89B01D3679253), - UINT64CONST(0x39D9B93D2959C9E6), UINT64CONST(0x7B2958D680B3FF75), - UINT64CONST(0xF50B1CAF74CF481F), UINT64CONST(0xB7FBFD44DD257E8C), - UINT64CONST(0x70EADF78271B2539), UINT64CONST(0x321A3E938EF113AA), - UINT64CONST(0x2E5EB66066087D7E), UINT64CONST(0x6CAE578BCFE24BED), - UINT64CONST(0xABBF75B735DC1058), UINT64CONST(0xE94F945C9C3626CB), - UINT64CONST(0x676DD025684A91A1), UINT64CONST(0x259D31CEC1A0A732), - UINT64CONST(0xE28C13F23B9EFC87), UINT64CONST(0xA07CF2199274CA14), - UINT64CONST(0x167FF3EACBAF2AF1), UINT64CONST(0x548F120162451C62), - UINT64CONST(0x939E303D987B47D7), UINT64CONST(0xD16ED1D631917144), - UINT64CONST(0x5F4C95AFC5EDC62E), UINT64CONST(0x1DBC74446C07F0BD), - UINT64CONST(0xDAAD56789639AB08), UINT64CONST(0x985DB7933FD39D9B), - UINT64CONST(0x84193F60D72AF34F), UINT64CONST(0xC6E9DE8B7EC0C5DC), - UINT64CONST(0x01F8FCB784FE9E69), UINT64CONST(0x43081D5C2D14A8FA), - UINT64CONST(0xCD2A5925D9681F90), UINT64CONST(0x8FDAB8CE70822903), - UINT64CONST(0x48CB9AF28ABC72B6), UINT64CONST(0x0A3B7B1923564425), - UINT64CONST(0x70428B155B4EAF1E), UINT64CONST(0x32B26AFEF2A4998D), - UINT64CONST(0xF5A348C2089AC238), UINT64CONST(0xB753A929A170F4AB), - UINT64CONST(0x3971ED50550C43C1), UINT64CONST(0x7B810CBBFCE67552), - UINT64CONST(0xBC902E8706D82EE7), UINT64CONST(0xFE60CF6CAF321874), - UINT64CONST(0xE224479F47CB76A0), UINT64CONST(0xA0D4A674EE214033), - UINT64CONST(0x67C58448141F1B86), UINT64CONST(0x253565A3BDF52D15), - UINT64CONST(0xAB1721DA49899A7F), UINT64CONST(0xE9E7C031E063ACEC), - UINT64CONST(0x2EF6E20D1A5DF759), UINT64CONST(0x6C0603E6B3B7C1CA), - UINT64CONST(0xF6FAE5C07D3274CD), UINT64CONST(0xB40A042BD4D8425E), - UINT64CONST(0x731B26172EE619EB), UINT64CONST(0x31EBC7FC870C2F78), - UINT64CONST(0xBFC9838573709812), UINT64CONST(0xFD39626EDA9AAE81), - UINT64CONST(0x3A28405220A4F534), UINT64CONST(0x78D8A1B9894EC3A7), - UINT64CONST(0x649C294A61B7AD73), UINT64CONST(0x266CC8A1C85D9BE0), - UINT64CONST(0xE17DEA9D3263C055), UINT64CONST(0xA38D0B769B89F6C6), - UINT64CONST(0x2DAF4F0F6FF541AC), UINT64CONST(0x6F5FAEE4C61F773F), - UINT64CONST(0xA84E8CD83C212C8A), UINT64CONST(0xEABE6D3395CB1A19), - UINT64CONST(0x90C79D3FEDD3F122), UINT64CONST(0xD2377CD44439C7B1), - UINT64CONST(0x15265EE8BE079C04), UINT64CONST(0x57D6BF0317EDAA97), - UINT64CONST(0xD9F4FB7AE3911DFD), UINT64CONST(0x9B041A914A7B2B6E), - UINT64CONST(0x5C1538ADB04570DB), UINT64CONST(0x1EE5D94619AF4648), - UINT64CONST(0x02A151B5F156289C), UINT64CONST(0x4051B05E58BC1E0F), - UINT64CONST(0x87409262A28245BA), UINT64CONST(0xC5B073890B687329), - UINT64CONST(0x4B9237F0FF14C443), UINT64CONST(0x0962D61B56FEF2D0), - UINT64CONST(0xCE73F427ACC0A965), UINT64CONST(0x8C8315CC052A9FF6), - UINT64CONST(0x3A80143F5CF17F13), UINT64CONST(0x7870F5D4F51B4980), - UINT64CONST(0xBF61D7E80F251235), UINT64CONST(0xFD913603A6CF24A6), - UINT64CONST(0x73B3727A52B393CC), UINT64CONST(0x31439391FB59A55F), - UINT64CONST(0xF652B1AD0167FEEA), UINT64CONST(0xB4A25046A88DC879), - UINT64CONST(0xA8E6D8B54074A6AD), UINT64CONST(0xEA16395EE99E903E), - UINT64CONST(0x2D071B6213A0CB8B), UINT64CONST(0x6FF7FA89BA4AFD18), - UINT64CONST(0xE1D5BEF04E364A72), UINT64CONST(0xA3255F1BE7DC7CE1), - UINT64CONST(0x64347D271DE22754), UINT64CONST(0x26C49CCCB40811C7), - UINT64CONST(0x5CBD6CC0CC10FAFC), UINT64CONST(0x1E4D8D2B65FACC6F), - UINT64CONST(0xD95CAF179FC497DA), UINT64CONST(0x9BAC4EFC362EA149), - UINT64CONST(0x158E0A85C2521623), UINT64CONST(0x577EEB6E6BB820B0), - UINT64CONST(0x906FC95291867B05), UINT64CONST(0xD29F28B9386C4D96), - UINT64CONST(0xCEDBA04AD0952342), UINT64CONST(0x8C2B41A1797F15D1), - UINT64CONST(0x4B3A639D83414E64), UINT64CONST(0x09CA82762AAB78F7), - UINT64CONST(0x87E8C60FDED7CF9D), UINT64CONST(0xC51827E4773DF90E), - UINT64CONST(0x020905D88D03A2BB), UINT64CONST(0x40F9E43324E99428), - UINT64CONST(0x2CFFE7D5975E55E2), UINT64CONST(0x6E0F063E3EB46371), - UINT64CONST(0xA91E2402C48A38C4), UINT64CONST(0xEBEEC5E96D600E57), - UINT64CONST(0x65CC8190991CB93D), UINT64CONST(0x273C607B30F68FAE), - UINT64CONST(0xE02D4247CAC8D41B), UINT64CONST(0xA2DDA3AC6322E288), - UINT64CONST(0xBE992B5F8BDB8C5C), UINT64CONST(0xFC69CAB42231BACF), - UINT64CONST(0x3B78E888D80FE17A), UINT64CONST(0x7988096371E5D7E9), - UINT64CONST(0xF7AA4D1A85996083), UINT64CONST(0xB55AACF12C735610), - UINT64CONST(0x724B8ECDD64D0DA5), UINT64CONST(0x30BB6F267FA73B36), - UINT64CONST(0x4AC29F2A07BFD00D), UINT64CONST(0x08327EC1AE55E69E), - UINT64CONST(0xCF235CFD546BBD2B), UINT64CONST(0x8DD3BD16FD818BB8), - UINT64CONST(0x03F1F96F09FD3CD2), UINT64CONST(0x41011884A0170A41), - UINT64CONST(0x86103AB85A2951F4), UINT64CONST(0xC4E0DB53F3C36767), - UINT64CONST(0xD8A453A01B3A09B3), UINT64CONST(0x9A54B24BB2D03F20), - UINT64CONST(0x5D45907748EE6495), UINT64CONST(0x1FB5719CE1045206), - UINT64CONST(0x919735E51578E56C), UINT64CONST(0xD367D40EBC92D3FF), - UINT64CONST(0x1476F63246AC884A), UINT64CONST(0x568617D9EF46BED9), - UINT64CONST(0xE085162AB69D5E3C), UINT64CONST(0xA275F7C11F7768AF), - UINT64CONST(0x6564D5FDE549331A), UINT64CONST(0x279434164CA30589), - UINT64CONST(0xA9B6706FB8DFB2E3), UINT64CONST(0xEB46918411358470), - UINT64CONST(0x2C57B3B8EB0BDFC5), UINT64CONST(0x6EA7525342E1E956), - UINT64CONST(0x72E3DAA0AA188782), UINT64CONST(0x30133B4B03F2B111), - UINT64CONST(0xF7021977F9CCEAA4), UINT64CONST(0xB5F2F89C5026DC37), - UINT64CONST(0x3BD0BCE5A45A6B5D), UINT64CONST(0x79205D0E0DB05DCE), - UINT64CONST(0xBE317F32F78E067B), UINT64CONST(0xFCC19ED95E6430E8), - UINT64CONST(0x86B86ED5267CDBD3), UINT64CONST(0xC4488F3E8F96ED40), - UINT64CONST(0x0359AD0275A8B6F5), UINT64CONST(0x41A94CE9DC428066), - UINT64CONST(0xCF8B0890283E370C), UINT64CONST(0x8D7BE97B81D4019F), - UINT64CONST(0x4A6ACB477BEA5A2A), UINT64CONST(0x089A2AACD2006CB9), - UINT64CONST(0x14DEA25F3AF9026D), UINT64CONST(0x562E43B4931334FE), - UINT64CONST(0x913F6188692D6F4B), UINT64CONST(0xD3CF8063C0C759D8), - UINT64CONST(0x5DEDC41A34BBEEB2), UINT64CONST(0x1F1D25F19D51D821), - UINT64CONST(0xD80C07CD676F8394), UINT64CONST(0x9AFCE626CE85B507) -}; -#endif /* INT64_IS_BUSTED */ - -#endif /* PROVIDE_64BIT_CRC */ +/*------------------------------------------------------------------------- + * + * pg_crc.c + * PostgreSQL CRC support + * + * See Ross Williams' excellent introduction + * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from + * http://www.ross.net/crc/download/crc_v3.txt or several other net sites. + * + * We use a normal (not "reflected", in Williams' terms) CRC, using initial + * all-ones register contents and a final bit inversion. + * + * The 64-bit variant is not used as of PostgreSQL 8.1, but we retain the + * code for possible future use. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/backend/utils/hash/pg_crc.c,v 1.21 2009/01/01 17:23:51 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + +/* Use c.h so that this file can be built in either frontend or backend */ +#include "c.h" + + +/* + * This table is based on the polynomial + * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + * (This is the same polynomial used in Ethernet checksums, for instance.) + */ +const uint32 pg_crc32_table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + + +#ifdef PROVIDE_64BIT_CRC + +/* + * This table is based on the polynomial + * + * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 + + * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 + + * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 + + * x^7 + x^4 + x + 1 + * + * which is borrowed from the DLT1 spec + * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM) + */ + +#ifdef INT64_IS_BUSTED + +const uint32 pg_crc64_table0[256] = { + 0x00000000, 0xA9EA3693, + 0x53D46D26, 0xFA3E5BB5, + 0x0E42ECDF, 0xA7A8DA4C, + 0x5D9681F9, 0xF47CB76A, + 0x1C85D9BE, 0xB56FEF2D, + 0x4F51B498, 0xE6BB820B, + 0x12C73561, 0xBB2D03F2, + 0x41135847, 0xE8F96ED4, + 0x90E185EF, 0x390BB37C, + 0xC335E8C9, 0x6ADFDE5A, + 0x9EA36930, 0x37495FA3, + 0xCD770416, 0x649D3285, + 0x8C645C51, 0x258E6AC2, + 0xDFB03177, 0x765A07E4, + 0x8226B08E, 0x2BCC861D, + 0xD1F2DDA8, 0x7818EB3B, + 0x21C30BDE, 0x88293D4D, + 0x721766F8, 0xDBFD506B, + 0x2F81E701, 0x866BD192, + 0x7C558A27, 0xD5BFBCB4, + 0x3D46D260, 0x94ACE4F3, + 0x6E92BF46, 0xC77889D5, + 0x33043EBF, 0x9AEE082C, + 0x60D05399, 0xC93A650A, + 0xB1228E31, 0x18C8B8A2, + 0xE2F6E317, 0x4B1CD584, + 0xBF6062EE, 0x168A547D, + 0xECB40FC8, 0x455E395B, + 0xADA7578F, 0x044D611C, + 0xFE733AA9, 0x57990C3A, + 0xA3E5BB50, 0x0A0F8DC3, + 0xF031D676, 0x59DBE0E5, + 0xEA6C212F, 0x438617BC, + 0xB9B84C09, 0x10527A9A, + 0xE42ECDF0, 0x4DC4FB63, + 0xB7FAA0D6, 0x1E109645, + 0xF6E9F891, 0x5F03CE02, + 0xA53D95B7, 0x0CD7A324, + 0xF8AB144E, 0x514122DD, + 0xAB7F7968, 0x02954FFB, + 0x7A8DA4C0, 0xD3679253, + 0x2959C9E6, 0x80B3FF75, + 0x74CF481F, 0xDD257E8C, + 0x271B2539, 0x8EF113AA, + 0x66087D7E, 0xCFE24BED, + 0x35DC1058, 0x9C3626CB, + 0x684A91A1, 0xC1A0A732, + 0x3B9EFC87, 0x9274CA14, + 0xCBAF2AF1, 0x62451C62, + 0x987B47D7, 0x31917144, + 0xC5EDC62E, 0x6C07F0BD, + 0x9639AB08, 0x3FD39D9B, + 0xD72AF34F, 0x7EC0C5DC, + 0x84FE9E69, 0x2D14A8FA, + 0xD9681F90, 0x70822903, + 0x8ABC72B6, 0x23564425, + 0x5B4EAF1E, 0xF2A4998D, + 0x089AC238, 0xA170F4AB, + 0x550C43C1, 0xFCE67552, + 0x06D82EE7, 0xAF321874, + 0x47CB76A0, 0xEE214033, + 0x141F1B86, 0xBDF52D15, + 0x49899A7F, 0xE063ACEC, + 0x1A5DF759, 0xB3B7C1CA, + 0x7D3274CD, 0xD4D8425E, + 0x2EE619EB, 0x870C2F78, + 0x73709812, 0xDA9AAE81, + 0x20A4F534, 0x894EC3A7, + 0x61B7AD73, 0xC85D9BE0, + 0x3263C055, 0x9B89F6C6, + 0x6FF541AC, 0xC61F773F, + 0x3C212C8A, 0x95CB1A19, + 0xEDD3F122, 0x4439C7B1, + 0xBE079C04, 0x17EDAA97, + 0xE3911DFD, 0x4A7B2B6E, + 0xB04570DB, 0x19AF4648, + 0xF156289C, 0x58BC1E0F, + 0xA28245BA, 0x0B687329, + 0xFF14C443, 0x56FEF2D0, + 0xACC0A965, 0x052A9FF6, + 0x5CF17F13, 0xF51B4980, + 0x0F251235, 0xA6CF24A6, + 0x52B393CC, 0xFB59A55F, + 0x0167FEEA, 0xA88DC879, + 0x4074A6AD, 0xE99E903E, + 0x13A0CB8B, 0xBA4AFD18, + 0x4E364A72, 0xE7DC7CE1, + 0x1DE22754, 0xB40811C7, + 0xCC10FAFC, 0x65FACC6F, + 0x9FC497DA, 0x362EA149, + 0xC2521623, 0x6BB820B0, + 0x91867B05, 0x386C4D96, + 0xD0952342, 0x797F15D1, + 0x83414E64, 0x2AAB78F7, + 0xDED7CF9D, 0x773DF90E, + 0x8D03A2BB, 0x24E99428, + 0x975E55E2, 0x3EB46371, + 0xC48A38C4, 0x6D600E57, + 0x991CB93D, 0x30F68FAE, + 0xCAC8D41B, 0x6322E288, + 0x8BDB8C5C, 0x2231BACF, + 0xD80FE17A, 0x71E5D7E9, + 0x85996083, 0x2C735610, + 0xD64D0DA5, 0x7FA73B36, + 0x07BFD00D, 0xAE55E69E, + 0x546BBD2B, 0xFD818BB8, + 0x09FD3CD2, 0xA0170A41, + 0x5A2951F4, 0xF3C36767, + 0x1B3A09B3, 0xB2D03F20, + 0x48EE6495, 0xE1045206, + 0x1578E56C, 0xBC92D3FF, + 0x46AC884A, 0xEF46BED9, + 0xB69D5E3C, 0x1F7768AF, + 0xE549331A, 0x4CA30589, + 0xB8DFB2E3, 0x11358470, + 0xEB0BDFC5, 0x42E1E956, + 0xAA188782, 0x03F2B111, + 0xF9CCEAA4, 0x5026DC37, + 0xA45A6B5D, 0x0DB05DCE, + 0xF78E067B, 0x5E6430E8, + 0x267CDBD3, 0x8F96ED40, + 0x75A8B6F5, 0xDC428066, + 0x283E370C, 0x81D4019F, + 0x7BEA5A2A, 0xD2006CB9, + 0x3AF9026D, 0x931334FE, + 0x692D6F4B, 0xC0C759D8, + 0x34BBEEB2, 0x9D51D821, + 0x676F8394, 0xCE85B507 +}; + +const uint32 pg_crc64_table1[256] = { + 0x00000000, 0x42F0E1EB, + 0x85E1C3D7, 0xC711223C, + 0x49336645, 0x0BC387AE, + 0xCCD2A592, 0x8E224479, + 0x9266CC8A, 0xD0962D61, + 0x17870F5D, 0x5577EEB6, + 0xDB55AACF, 0x99A54B24, + 0x5EB46918, 0x1C4488F3, + 0x663D78FF, 0x24CD9914, + 0xE3DCBB28, 0xA12C5AC3, + 0x2F0E1EBA, 0x6DFEFF51, + 0xAAEFDD6D, 0xE81F3C86, + 0xF45BB475, 0xB6AB559E, + 0x71BA77A2, 0x334A9649, + 0xBD68D230, 0xFF9833DB, + 0x388911E7, 0x7A79F00C, + 0xCC7AF1FF, 0x8E8A1014, + 0x499B3228, 0x0B6BD3C3, + 0x854997BA, 0xC7B97651, + 0x00A8546D, 0x4258B586, + 0x5E1C3D75, 0x1CECDC9E, + 0xDBFDFEA2, 0x990D1F49, + 0x172F5B30, 0x55DFBADB, + 0x92CE98E7, 0xD03E790C, + 0xAA478900, 0xE8B768EB, + 0x2FA64AD7, 0x6D56AB3C, + 0xE374EF45, 0xA1840EAE, + 0x66952C92, 0x2465CD79, + 0x3821458A, 0x7AD1A461, + 0xBDC0865D, 0xFF3067B6, + 0x711223CF, 0x33E2C224, + 0xF4F3E018, 0xB60301F3, + 0xDA050215, 0x98F5E3FE, + 0x5FE4C1C2, 0x1D142029, + 0x93366450, 0xD1C685BB, + 0x16D7A787, 0x5427466C, + 0x4863CE9F, 0x0A932F74, + 0xCD820D48, 0x8F72ECA3, + 0x0150A8DA, 0x43A04931, + 0x84B16B0D, 0xC6418AE6, + 0xBC387AEA, 0xFEC89B01, + 0x39D9B93D, 0x7B2958D6, + 0xF50B1CAF, 0xB7FBFD44, + 0x70EADF78, 0x321A3E93, + 0x2E5EB660, 0x6CAE578B, + 0xABBF75B7, 0xE94F945C, + 0x676DD025, 0x259D31CE, + 0xE28C13F2, 0xA07CF219, + 0x167FF3EA, 0x548F1201, + 0x939E303D, 0xD16ED1D6, + 0x5F4C95AF, 0x1DBC7444, + 0xDAAD5678, 0x985DB793, + 0x84193F60, 0xC6E9DE8B, + 0x01F8FCB7, 0x43081D5C, + 0xCD2A5925, 0x8FDAB8CE, + 0x48CB9AF2, 0x0A3B7B19, + 0x70428B15, 0x32B26AFE, + 0xF5A348C2, 0xB753A929, + 0x3971ED50, 0x7B810CBB, + 0xBC902E87, 0xFE60CF6C, + 0xE224479F, 0xA0D4A674, + 0x67C58448, 0x253565A3, + 0xAB1721DA, 0xE9E7C031, + 0x2EF6E20D, 0x6C0603E6, + 0xF6FAE5C0, 0xB40A042B, + 0x731B2617, 0x31EBC7FC, + 0xBFC98385, 0xFD39626E, + 0x3A284052, 0x78D8A1B9, + 0x649C294A, 0x266CC8A1, + 0xE17DEA9D, 0xA38D0B76, + 0x2DAF4F0F, 0x6F5FAEE4, + 0xA84E8CD8, 0xEABE6D33, + 0x90C79D3F, 0xD2377CD4, + 0x15265EE8, 0x57D6BF03, + 0xD9F4FB7A, 0x9B041A91, + 0x5C1538AD, 0x1EE5D946, + 0x02A151B5, 0x4051B05E, + 0x87409262, 0xC5B07389, + 0x4B9237F0, 0x0962D61B, + 0xCE73F427, 0x8C8315CC, + 0x3A80143F, 0x7870F5D4, + 0xBF61D7E8, 0xFD913603, + 0x73B3727A, 0x31439391, + 0xF652B1AD, 0xB4A25046, + 0xA8E6D8B5, 0xEA16395E, + 0x2D071B62, 0x6FF7FA89, + 0xE1D5BEF0, 0xA3255F1B, + 0x64347D27, 0x26C49CCC, + 0x5CBD6CC0, 0x1E4D8D2B, + 0xD95CAF17, 0x9BAC4EFC, + 0x158E0A85, 0x577EEB6E, + 0x906FC952, 0xD29F28B9, + 0xCEDBA04A, 0x8C2B41A1, + 0x4B3A639D, 0x09CA8276, + 0x87E8C60F, 0xC51827E4, + 0x020905D8, 0x40F9E433, + 0x2CFFE7D5, 0x6E0F063E, + 0xA91E2402, 0xEBEEC5E9, + 0x65CC8190, 0x273C607B, + 0xE02D4247, 0xA2DDA3AC, + 0xBE992B5F, 0xFC69CAB4, + 0x3B78E888, 0x79880963, + 0xF7AA4D1A, 0xB55AACF1, + 0x724B8ECD, 0x30BB6F26, + 0x4AC29F2A, 0x08327EC1, + 0xCF235CFD, 0x8DD3BD16, + 0x03F1F96F, 0x41011884, + 0x86103AB8, 0xC4E0DB53, + 0xD8A453A0, 0x9A54B24B, + 0x5D459077, 0x1FB5719C, + 0x919735E5, 0xD367D40E, + 0x1476F632, 0x568617D9, + 0xE085162A, 0xA275F7C1, + 0x6564D5FD, 0x27943416, + 0xA9B6706F, 0xEB469184, + 0x2C57B3B8, 0x6EA75253, + 0x72E3DAA0, 0x30133B4B, + 0xF7021977, 0xB5F2F89C, + 0x3BD0BCE5, 0x79205D0E, + 0xBE317F32, 0xFCC19ED9, + 0x86B86ED5, 0xC4488F3E, + 0x0359AD02, 0x41A94CE9, + 0xCF8B0890, 0x8D7BE97B, + 0x4A6ACB47, 0x089A2AAC, + 0x14DEA25F, 0x562E43B4, + 0x913F6188, 0xD3CF8063, + 0x5DEDC41A, 0x1F1D25F1, + 0xD80C07CD, 0x9AFCE626 +}; +#else /* int64 works */ + +const uint64 pg_crc64_table[256] = { + UINT64CONST(0x0000000000000000), UINT64CONST(0x42F0E1EBA9EA3693), + UINT64CONST(0x85E1C3D753D46D26), UINT64CONST(0xC711223CFA3E5BB5), + UINT64CONST(0x493366450E42ECDF), UINT64CONST(0x0BC387AEA7A8DA4C), + UINT64CONST(0xCCD2A5925D9681F9), UINT64CONST(0x8E224479F47CB76A), + UINT64CONST(0x9266CC8A1C85D9BE), UINT64CONST(0xD0962D61B56FEF2D), + UINT64CONST(0x17870F5D4F51B498), UINT64CONST(0x5577EEB6E6BB820B), + UINT64CONST(0xDB55AACF12C73561), UINT64CONST(0x99A54B24BB2D03F2), + UINT64CONST(0x5EB4691841135847), UINT64CONST(0x1C4488F3E8F96ED4), + UINT64CONST(0x663D78FF90E185EF), UINT64CONST(0x24CD9914390BB37C), + UINT64CONST(0xE3DCBB28C335E8C9), UINT64CONST(0xA12C5AC36ADFDE5A), + UINT64CONST(0x2F0E1EBA9EA36930), UINT64CONST(0x6DFEFF5137495FA3), + UINT64CONST(0xAAEFDD6DCD770416), UINT64CONST(0xE81F3C86649D3285), + UINT64CONST(0xF45BB4758C645C51), UINT64CONST(0xB6AB559E258E6AC2), + UINT64CONST(0x71BA77A2DFB03177), UINT64CONST(0x334A9649765A07E4), + UINT64CONST(0xBD68D2308226B08E), UINT64CONST(0xFF9833DB2BCC861D), + UINT64CONST(0x388911E7D1F2DDA8), UINT64CONST(0x7A79F00C7818EB3B), + UINT64CONST(0xCC7AF1FF21C30BDE), UINT64CONST(0x8E8A101488293D4D), + UINT64CONST(0x499B3228721766F8), UINT64CONST(0x0B6BD3C3DBFD506B), + UINT64CONST(0x854997BA2F81E701), UINT64CONST(0xC7B97651866BD192), + UINT64CONST(0x00A8546D7C558A27), UINT64CONST(0x4258B586D5BFBCB4), + UINT64CONST(0x5E1C3D753D46D260), UINT64CONST(0x1CECDC9E94ACE4F3), + UINT64CONST(0xDBFDFEA26E92BF46), UINT64CONST(0x990D1F49C77889D5), + UINT64CONST(0x172F5B3033043EBF), UINT64CONST(0x55DFBADB9AEE082C), + UINT64CONST(0x92CE98E760D05399), UINT64CONST(0xD03E790CC93A650A), + UINT64CONST(0xAA478900B1228E31), UINT64CONST(0xE8B768EB18C8B8A2), + UINT64CONST(0x2FA64AD7E2F6E317), UINT64CONST(0x6D56AB3C4B1CD584), + UINT64CONST(0xE374EF45BF6062EE), UINT64CONST(0xA1840EAE168A547D), + UINT64CONST(0x66952C92ECB40FC8), UINT64CONST(0x2465CD79455E395B), + UINT64CONST(0x3821458AADA7578F), UINT64CONST(0x7AD1A461044D611C), + UINT64CONST(0xBDC0865DFE733AA9), UINT64CONST(0xFF3067B657990C3A), + UINT64CONST(0x711223CFA3E5BB50), UINT64CONST(0x33E2C2240A0F8DC3), + UINT64CONST(0xF4F3E018F031D676), UINT64CONST(0xB60301F359DBE0E5), + UINT64CONST(0xDA050215EA6C212F), UINT64CONST(0x98F5E3FE438617BC), + UINT64CONST(0x5FE4C1C2B9B84C09), UINT64CONST(0x1D14202910527A9A), + UINT64CONST(0x93366450E42ECDF0), UINT64CONST(0xD1C685BB4DC4FB63), + UINT64CONST(0x16D7A787B7FAA0D6), UINT64CONST(0x5427466C1E109645), + UINT64CONST(0x4863CE9FF6E9F891), UINT64CONST(0x0A932F745F03CE02), + UINT64CONST(0xCD820D48A53D95B7), UINT64CONST(0x8F72ECA30CD7A324), + UINT64CONST(0x0150A8DAF8AB144E), UINT64CONST(0x43A04931514122DD), + UINT64CONST(0x84B16B0DAB7F7968), UINT64CONST(0xC6418AE602954FFB), + UINT64CONST(0xBC387AEA7A8DA4C0), UINT64CONST(0xFEC89B01D3679253), + UINT64CONST(0x39D9B93D2959C9E6), UINT64CONST(0x7B2958D680B3FF75), + UINT64CONST(0xF50B1CAF74CF481F), UINT64CONST(0xB7FBFD44DD257E8C), + UINT64CONST(0x70EADF78271B2539), UINT64CONST(0x321A3E938EF113AA), + UINT64CONST(0x2E5EB66066087D7E), UINT64CONST(0x6CAE578BCFE24BED), + UINT64CONST(0xABBF75B735DC1058), UINT64CONST(0xE94F945C9C3626CB), + UINT64CONST(0x676DD025684A91A1), UINT64CONST(0x259D31CEC1A0A732), + UINT64CONST(0xE28C13F23B9EFC87), UINT64CONST(0xA07CF2199274CA14), + UINT64CONST(0x167FF3EACBAF2AF1), UINT64CONST(0x548F120162451C62), + UINT64CONST(0x939E303D987B47D7), UINT64CONST(0xD16ED1D631917144), + UINT64CONST(0x5F4C95AFC5EDC62E), UINT64CONST(0x1DBC74446C07F0BD), + UINT64CONST(0xDAAD56789639AB08), UINT64CONST(0x985DB7933FD39D9B), + UINT64CONST(0x84193F60D72AF34F), UINT64CONST(0xC6E9DE8B7EC0C5DC), + UINT64CONST(0x01F8FCB784FE9E69), UINT64CONST(0x43081D5C2D14A8FA), + UINT64CONST(0xCD2A5925D9681F90), UINT64CONST(0x8FDAB8CE70822903), + UINT64CONST(0x48CB9AF28ABC72B6), UINT64CONST(0x0A3B7B1923564425), + UINT64CONST(0x70428B155B4EAF1E), UINT64CONST(0x32B26AFEF2A4998D), + UINT64CONST(0xF5A348C2089AC238), UINT64CONST(0xB753A929A170F4AB), + UINT64CONST(0x3971ED50550C43C1), UINT64CONST(0x7B810CBBFCE67552), + UINT64CONST(0xBC902E8706D82EE7), UINT64CONST(0xFE60CF6CAF321874), + UINT64CONST(0xE224479F47CB76A0), UINT64CONST(0xA0D4A674EE214033), + UINT64CONST(0x67C58448141F1B86), UINT64CONST(0x253565A3BDF52D15), + UINT64CONST(0xAB1721DA49899A7F), UINT64CONST(0xE9E7C031E063ACEC), + UINT64CONST(0x2EF6E20D1A5DF759), UINT64CONST(0x6C0603E6B3B7C1CA), + UINT64CONST(0xF6FAE5C07D3274CD), UINT64CONST(0xB40A042BD4D8425E), + UINT64CONST(0x731B26172EE619EB), UINT64CONST(0x31EBC7FC870C2F78), + UINT64CONST(0xBFC9838573709812), UINT64CONST(0xFD39626EDA9AAE81), + UINT64CONST(0x3A28405220A4F534), UINT64CONST(0x78D8A1B9894EC3A7), + UINT64CONST(0x649C294A61B7AD73), UINT64CONST(0x266CC8A1C85D9BE0), + UINT64CONST(0xE17DEA9D3263C055), UINT64CONST(0xA38D0B769B89F6C6), + UINT64CONST(0x2DAF4F0F6FF541AC), UINT64CONST(0x6F5FAEE4C61F773F), + UINT64CONST(0xA84E8CD83C212C8A), UINT64CONST(0xEABE6D3395CB1A19), + UINT64CONST(0x90C79D3FEDD3F122), UINT64CONST(0xD2377CD44439C7B1), + UINT64CONST(0x15265EE8BE079C04), UINT64CONST(0x57D6BF0317EDAA97), + UINT64CONST(0xD9F4FB7AE3911DFD), UINT64CONST(0x9B041A914A7B2B6E), + UINT64CONST(0x5C1538ADB04570DB), UINT64CONST(0x1EE5D94619AF4648), + UINT64CONST(0x02A151B5F156289C), UINT64CONST(0x4051B05E58BC1E0F), + UINT64CONST(0x87409262A28245BA), UINT64CONST(0xC5B073890B687329), + UINT64CONST(0x4B9237F0FF14C443), UINT64CONST(0x0962D61B56FEF2D0), + UINT64CONST(0xCE73F427ACC0A965), UINT64CONST(0x8C8315CC052A9FF6), + UINT64CONST(0x3A80143F5CF17F13), UINT64CONST(0x7870F5D4F51B4980), + UINT64CONST(0xBF61D7E80F251235), UINT64CONST(0xFD913603A6CF24A6), + UINT64CONST(0x73B3727A52B393CC), UINT64CONST(0x31439391FB59A55F), + UINT64CONST(0xF652B1AD0167FEEA), UINT64CONST(0xB4A25046A88DC879), + UINT64CONST(0xA8E6D8B54074A6AD), UINT64CONST(0xEA16395EE99E903E), + UINT64CONST(0x2D071B6213A0CB8B), UINT64CONST(0x6FF7FA89BA4AFD18), + UINT64CONST(0xE1D5BEF04E364A72), UINT64CONST(0xA3255F1BE7DC7CE1), + UINT64CONST(0x64347D271DE22754), UINT64CONST(0x26C49CCCB40811C7), + UINT64CONST(0x5CBD6CC0CC10FAFC), UINT64CONST(0x1E4D8D2B65FACC6F), + UINT64CONST(0xD95CAF179FC497DA), UINT64CONST(0x9BAC4EFC362EA149), + UINT64CONST(0x158E0A85C2521623), UINT64CONST(0x577EEB6E6BB820B0), + UINT64CONST(0x906FC95291867B05), UINT64CONST(0xD29F28B9386C4D96), + UINT64CONST(0xCEDBA04AD0952342), UINT64CONST(0x8C2B41A1797F15D1), + UINT64CONST(0x4B3A639D83414E64), UINT64CONST(0x09CA82762AAB78F7), + UINT64CONST(0x87E8C60FDED7CF9D), UINT64CONST(0xC51827E4773DF90E), + UINT64CONST(0x020905D88D03A2BB), UINT64CONST(0x40F9E43324E99428), + UINT64CONST(0x2CFFE7D5975E55E2), UINT64CONST(0x6E0F063E3EB46371), + UINT64CONST(0xA91E2402C48A38C4), UINT64CONST(0xEBEEC5E96D600E57), + UINT64CONST(0x65CC8190991CB93D), UINT64CONST(0x273C607B30F68FAE), + UINT64CONST(0xE02D4247CAC8D41B), UINT64CONST(0xA2DDA3AC6322E288), + UINT64CONST(0xBE992B5F8BDB8C5C), UINT64CONST(0xFC69CAB42231BACF), + UINT64CONST(0x3B78E888D80FE17A), UINT64CONST(0x7988096371E5D7E9), + UINT64CONST(0xF7AA4D1A85996083), UINT64CONST(0xB55AACF12C735610), + UINT64CONST(0x724B8ECDD64D0DA5), UINT64CONST(0x30BB6F267FA73B36), + UINT64CONST(0x4AC29F2A07BFD00D), UINT64CONST(0x08327EC1AE55E69E), + UINT64CONST(0xCF235CFD546BBD2B), UINT64CONST(0x8DD3BD16FD818BB8), + UINT64CONST(0x03F1F96F09FD3CD2), UINT64CONST(0x41011884A0170A41), + UINT64CONST(0x86103AB85A2951F4), UINT64CONST(0xC4E0DB53F3C36767), + UINT64CONST(0xD8A453A01B3A09B3), UINT64CONST(0x9A54B24BB2D03F20), + UINT64CONST(0x5D45907748EE6495), UINT64CONST(0x1FB5719CE1045206), + UINT64CONST(0x919735E51578E56C), UINT64CONST(0xD367D40EBC92D3FF), + UINT64CONST(0x1476F63246AC884A), UINT64CONST(0x568617D9EF46BED9), + UINT64CONST(0xE085162AB69D5E3C), UINT64CONST(0xA275F7C11F7768AF), + UINT64CONST(0x6564D5FDE549331A), UINT64CONST(0x279434164CA30589), + UINT64CONST(0xA9B6706FB8DFB2E3), UINT64CONST(0xEB46918411358470), + UINT64CONST(0x2C57B3B8EB0BDFC5), UINT64CONST(0x6EA7525342E1E956), + UINT64CONST(0x72E3DAA0AA188782), UINT64CONST(0x30133B4B03F2B111), + UINT64CONST(0xF7021977F9CCEAA4), UINT64CONST(0xB5F2F89C5026DC37), + UINT64CONST(0x3BD0BCE5A45A6B5D), UINT64CONST(0x79205D0E0DB05DCE), + UINT64CONST(0xBE317F32F78E067B), UINT64CONST(0xFCC19ED95E6430E8), + UINT64CONST(0x86B86ED5267CDBD3), UINT64CONST(0xC4488F3E8F96ED40), + UINT64CONST(0x0359AD0275A8B6F5), UINT64CONST(0x41A94CE9DC428066), + UINT64CONST(0xCF8B0890283E370C), UINT64CONST(0x8D7BE97B81D4019F), + UINT64CONST(0x4A6ACB477BEA5A2A), UINT64CONST(0x089A2AACD2006CB9), + UINT64CONST(0x14DEA25F3AF9026D), UINT64CONST(0x562E43B4931334FE), + UINT64CONST(0x913F6188692D6F4B), UINT64CONST(0xD3CF8063C0C759D8), + UINT64CONST(0x5DEDC41A34BBEEB2), UINT64CONST(0x1F1D25F19D51D821), + UINT64CONST(0xD80C07CD676F8394), UINT64CONST(0x9AFCE626CE85B507) +}; +#endif /* INT64_IS_BUSTED */ + +#endif /* PROVIDE_64BIT_CRC */ diff --git a/pgsql_src/pg_ctl.c b/pgsql_src/pg_ctl.c index 90ed71f8..b39ae0fe 100644 --- a/pgsql_src/pg_ctl.c +++ b/pgsql_src/pg_ctl.c @@ -1,105 +1,105 @@ -/*------------------------------------------------------------------------- - * - * pg_ctl --- start/stops/restarts the PostgreSQL server - * - * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group - * - * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.111 2009/06/11 14:49:07 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - - -#include "postgres_fe.h" - -#include -#include -#include - -#include "pg_rman.h" - -/* PID can be negative for standalone backend */ -typedef long pgpid_t; - -static pgpid_t get_pgpid(void); -static bool postmaster_is_alive(pid_t pid); - -static char pid_file[MAXPGPATH]; - - -static pgpid_t -get_pgpid(void) -{ - FILE *pidf; - long pid; - - snprintf(pid_file, lengthof(pid_file), "%s/postmaster.pid", pgdata); - pidf = fopen(pid_file, "r"); - if (pidf == NULL) - { - /* No pid file, not an error on startup */ - if (errno == ENOENT) - return 0; - else - elog(ERROR_SYSTEM, _("could not open PID file \"%s\": %s\n"), - pid_file, strerror(errno)); - } - if (fscanf(pidf, "%ld", &pid) != 1) - elog(ERROR_PID_BROKEN, _("invalid data in PID file \"%s\"\n"), pid_file); - fclose(pidf); - return (pgpid_t) pid; -} - -/* - * utility routines - */ - -static bool -postmaster_is_alive(pid_t pid) -{ - /* - * Test to see if the process is still there. Note that we do not - * consider an EPERM failure to mean that the process is still there; - * EPERM must mean that the given PID belongs to some other userid, and - * considering the permissions on $PGDATA, that means it's not the - * postmaster we are after. - * - * Don't believe that our own PID or parent shell's PID is the postmaster, - * either. (Windows hasn't got getppid(), though.) - */ - if (pid == getpid()) - return false; -#ifndef WIN32 - if (pid == getppid()) - return false; -#endif - if (kill(pid, 0) == 0) - return true; - return false; -} - -/* - * original is do_status() in src/bin/pg_ctl/pg_ctl.c - * changes are: - * renamed from do_status() from do_status(). - * return true if PG server is running. - * don't print any message. - * don't print postopts file. - * log with elog() in pgut library. - */ -bool -is_pg_running(void) -{ - pgpid_t pid; - - pid = get_pgpid(); - if (pid == 0) /* 0 means no pid file */ - return false; - - if (pid < 0) /* standalone backend */ - pid = -pid; - - - return postmaster_is_alive((pid_t) pid); -} - +/*------------------------------------------------------------------------- + * + * pg_ctl --- start/stops/restarts the PostgreSQL server + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * + * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.111 2009/06/11 14:49:07 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + + +#include "postgres_fe.h" + +#include +#include +#include + +#include "pg_rman.h" + +/* PID can be negative for standalone backend */ +typedef long pgpid_t; + +static pgpid_t get_pgpid(void); +static bool postmaster_is_alive(pid_t pid); + +static char pid_file[MAXPGPATH]; + + +static pgpid_t +get_pgpid(void) +{ + FILE *pidf; + long pid; + + snprintf(pid_file, lengthof(pid_file), "%s/postmaster.pid", pgdata); + pidf = fopen(pid_file, "r"); + if (pidf == NULL) + { + /* No pid file, not an error on startup */ + if (errno == ENOENT) + return 0; + else + elog(ERROR_SYSTEM, _("could not open PID file \"%s\": %s\n"), + pid_file, strerror(errno)); + } + if (fscanf(pidf, "%ld", &pid) != 1) + elog(ERROR_PID_BROKEN, _("invalid data in PID file \"%s\"\n"), pid_file); + fclose(pidf); + return (pgpid_t) pid; +} + +/* + * utility routines + */ + +static bool +postmaster_is_alive(pid_t pid) +{ + /* + * Test to see if the process is still there. Note that we do not + * consider an EPERM failure to mean that the process is still there; + * EPERM must mean that the given PID belongs to some other userid, and + * considering the permissions on $PGDATA, that means it's not the + * postmaster we are after. + * + * Don't believe that our own PID or parent shell's PID is the postmaster, + * either. (Windows hasn't got getppid(), though.) + */ + if (pid == getpid()) + return false; +#ifndef WIN32 + if (pid == getppid()) + return false; +#endif + if (kill(pid, 0) == 0) + return true; + return false; +} + +/* + * original is do_status() in src/bin/pg_ctl/pg_ctl.c + * changes are: + * renamed from do_status() from do_status(). + * return true if PG server is running. + * don't print any message. + * don't print postopts file. + * log with elog() in pgut library. + */ +bool +is_pg_running(void) +{ + pgpid_t pid; + + pid = get_pgpid(); + if (pid == 0) /* 0 means no pid file */ + return false; + + if (pid < 0) /* standalone backend */ + pid = -pid; + + + return postmaster_is_alive((pid_t) pid); +} + diff --git a/pgut/pgut.c b/pgut/pgut.c index a8dd340f..def6c9d6 100644 --- a/pgut/pgut.c +++ b/pgut/pgut.c @@ -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 diff --git a/queue.c b/queue.c index 5dd70ad8..367117db 100644 --- a/queue.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/restore.c b/restore.c index 0ad70bdd..18fea5a7 100644 --- a/restore.c +++ b/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; + +} diff --git a/show.c b/show.c index 254424a5..1b543c7b 100644 --- a/show.c +++ b/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); diff --git a/sql/backup_restore.sh b/sql/backup_restore.sh index 4f256497..f4c77e3a 100644 --- a/sql/backup_restore.sh +++ b/sql/backup_restore.sh @@ -1,274 +1,281 @@ -#!/bin/sh - -BASE_PATH=`pwd` -export PGDATA=$BASE_PATH/results/sample_database - -export BACKUP_PATH=$BASE_PATH/results/sample_backup2 -export ARCLOG_PATH=$BASE_PATH/results/arclog -export SRVLOG_PATH=$PGDATA/pg_log -export COMPRESS_DATA=YES -XLOG_PATH=$PGDATA/pg_xlog -TBLSPC_PATH=$BASE_PATH/results/tblspc - -# Port used for test database cluster -TEST_PGPORT=54321 - -# configuration -SCALE=1 -DURATION=10 -ISOLATE_SRVLOG=0 -ISOLATE_WAL=0 - -while [ $# -gt 0 ]; do - case $1 in - "-s") - ISOLATE_SRVLOG=1 - shift - ;; - "-w") - ISOLATE_WAL=1 - shift - ;; - "-d") - DURATION=`expr $2 + 0` - if [ $? -ne 0 ]; then - echo "invalid duration" - exit 1 - fi - shift 2 - ;; - "-s") - SCALE=`expr $2 + 0` - if [ $? -ne 0 ]; then - echo "invalid scale" - exit 1 - fi - shift 2 - ;; - *) - shift - ;; - esac -done - -# delete old database cluster -pg_ctl stop -m immediate > /dev/null 2>&1 -rm -rf $PGDATA -rm -rf $BASE_PATH/results/pg_xlog -rm -rf $BASE_PATH/results/srvlog -rm -rf $ARCLOG_PATH -rm -rf $SRVLOG_PATH -rm -rf $TBLSPC_PATH - -# create new backup catalog -rm -rf $BACKUP_PATH -pg_rman init -B $BACKUP_PATH --quiet - -# create default configuration file -cat << EOF > $BACKUP_PATH/pg_rman.ini - # comment - BACKUP_MODE = F # comment -EOF - -# create new database cluster -initdb --no-locale > $BASE_PATH/results/initdb.log 2>&1 -cat << EOF >> $PGDATA/postgresql.conf -port = $TEST_PGPORT -logging_collector = on -archive_mode = on -archive_command = 'cp "%p" "$ARCLOG_PATH/%f"' -EOF - -mkdir -p $ARCLOG_PATH -mkdir -p $TBLSPC_PATH - -# determine serverlog directory -if [ "$ISOLATE_SRVLOG" -ne 0 ]; then - export SRVLOG_PATH=$BASE_PATH/results/srvlog - echo "log_directory = '$SRVLOG_PATH'" >> $PGDATA/postgresql.conf - mkdir -p $SRVLOG_PATH -else - export SRVLOG_PATH=$PGDATA/pg_log - echo "log_directory = 'pg_log'" >> $PGDATA/postgresql.conf -fi - -# isolate online WAL -if [ "$ISOLATE_WAL" -ne 0 ]; then - XLOG_PATH=$BASE_PATH/results/pg_xlog - mv $PGDATA/pg_xlog $XLOG_PATH - ln -s $XLOG_PATH $PGDATA/pg_xlog -fi - -# start PostgreSQL -pg_ctl start -w -t 3600 > /dev/null 2>&1 - -# create tablespace and database for pgbench -mkdir -p $TBLSPC_PATH/pgbench -psql -p $TEST_PGPORT 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" -grep -c DELETED $BASE_PATH/results/log_show_d_1 - -pgbench -p $TEST_PGPORT -i -s $SCALE pgbench > $BASE_PATH/results/pgbench.log 2>&1 - -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 - -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 - -# 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 > $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 - -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 - -# stop PG during transaction and get commited info for verifing -echo "stop DB during running pgbench" -pgbench -p $TEST_PGPORT -T $DURATION -c 10 pgbench >> $BASE_PATH/results/pgbench.log 2>&1 & -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 > $BASE_PATH/results/dump_before.sql - -# revert to crushed cluster -pg_ctl stop > /dev/null 2>&1 -rm -rf $PGDATA -mv $PGDATA.bak $PGDATA - -# validate all backup -pg_rman validate `date +%Y` --verbose > $BASE_PATH/results/log_validate2 2>&1 - -# restore check with pg_rman -pg_rman restore -! --verbose --check > $BASE_PATH/results/log_restore_check_1 2>&1 - -# restore with pg_rman -CUR_TLI=`pg_controldata | grep TimeLineID | awk '{print $4}'` -pg_rman restore -! --verbose > $BASE_PATH/results/log_restore1_1 2>&1 -CUR_TLI_R=`grep "current timeline ID = " $BASE_PATH/results/log_restore1_1 | awk '{print $5}'` -TARGET_TLI=`grep "target timeline ID = " $BASE_PATH/results/log_restore1_1 | awk '{print $5}'` -if [ "$CUR_TLI" != "$CUR_TLI_R" -o "$CUR_TLI" != "$CUR_TLI_R" ]; then - echo "failed: bad timeline ID" CUR_TLI=$CUR_TLI CUR_TLI_R=$CUR_TLI_R -fi - -# Backup of online-WAL and serverlog. -echo "diff files in BACKUP_PATH/backup/pg_xlog" -diff -r $PGDATA/pg_xlog $BACKUP_PATH/backup/pg_xlog -echo "# of files in BACKUP_PATH/backup/srvlog" -find $BACKUP_PATH/backup/srvlog -type f | wc -l - -# recovery database -pg_ctl start -w -t 3600 > /dev/null 2>&1 - -# re-restore with pg_rman -pg_ctl stop -m immediate > /dev/null 2>&1 - -# restore check with pg_rman -pg_rman restore -! --verbose --check > $BASE_PATH/results/log_restore_check_2 2>&1 - -CUR_TLI=`pg_controldata | grep TimeLineID | awk '{print $4}'` -pg_rman restore -! --verbose > $BASE_PATH/results/log_restore1_2 2>&1 -CUR_TLI_R=`grep "current timeline ID = " $BASE_PATH/results/log_restore1_2 | awk '{print $5}'` -TARGET_TLI=`grep "target timeline ID = " $BASE_PATH/results/log_restore1_2 | awk '{print $5}'` -if [ "$CUR_TLI" != "$CUR_TLI_R" -o "$CUR_TLI" != "$CUR_TLI_R" ]; then - echo "failed: bad timeline ID" CUR_TLI=$CUR_TLI CUR_TLI_R=$CUR_TLI_R -fi - -# Backup of online-WAL and serverlog. -echo "diff files in BACKUP_PATH/backup/pg_xlog" -diff -r $PGDATA/pg_xlog $BACKUP_PATH/backup/pg_xlog -echo "# of files in BACKUP_PATH/backup/srvlog" -find $BACKUP_PATH/backup/srvlog -type f | wc -l - -# re-recovery database -pg_ctl start -w -t 3600 > /dev/null 2>&1 - -# compare recovery results -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 -# 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 - -# Backup of online-WAL should been deleted, but serverlog remain. -echo "# of files in BACKUP_PATH/backup/pg_xlog" -find $BACKUP_PATH/backup/pg_xlog -type f | wc -l -echo "# of files in BACKUP_PATH/backup/srvlog" -find $BACKUP_PATH/backup/srvlog -type f | wc -l - -# Symbolic links in $ARCLOG_PATH should be deleted. -echo "# of symbolic links in ARCLOG_PATH" -find $ARCLOG_PATH -type l | wc -l - -# timeline history files are backed up. -echo "# of files in BACKUP_PATH/timeline_history" -find $BACKUP_PATH/timeline_history -type f | wc -l - -# restore with pg_rman -pg_ctl stop -m immediate > /dev/null 2>&1 - -# restore check with pg_rman -pg_rman restore -! --verbose --check > $BASE_PATH/results/log_restore_check_3 2>&1 - -CUR_TLI=`pg_controldata | grep TimeLineID | awk '{print $4}'` -pg_rman restore -! --recovery-target-xid $target_xid --recovery-target-inclusive false --verbose > $BASE_PATH/results/log_restore2 2>&1 -CUR_TLI_R=`grep "current timeline ID = " $BASE_PATH/results/log_restore2 | awk '{print $5}'` -TARGET_TLI=`grep "target timeline ID = " $BASE_PATH/results/log_restore2 | awk '{print $5}'` -if [ "$CUR_TLI" != "$CUR_TLI_R" -o "$CUR_TLI" != "$CUR_TLI_R" ]; then - echo "failed: bad timeline ID" CUR_TLI=$CUR_TLI CUR_TLI_R=$CUR_TLI_R -fi -echo "# of recovery target option in recovery.conf" -grep -c "recovery_target_" $PGDATA/recovery.conf - -# recovery database -pg_ctl start -w -t 3600 > /dev/null 2>&1 - -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 -pg_rman -p $TEST_PGPORT show timeline --verbose -a -d postgres > $BASE_PATH/results/log_show_timeline_1 2>&1 -pg_rman -p $TEST_PGPORT show timeline `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show_timeline_2 2>&1 -pg_rman -p $TEST_PGPORT show timeline `date +%Y` --verbose -d postgres > $BASE_PATH/results/log_show_timeline_3 2>&1 -echo "# of deleted backups (show all)" -grep -c DELETED $BASE_PATH/results/log_show_timeline_2 -echo "# of deleted backups" -grep -c DELETED $BASE_PATH/results/log_show_timeline_3 - -echo "delete backup" -pg_rman -p $TEST_PGPORT delete --debug -d postgres > $BASE_PATH/results/log_delete1 2>&1 -pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show1 2>&1 -echo "# of deleted backups" -grep -c DELETED $BASE_PATH/results/log_show1 -pg_rman -p $TEST_PGPORT delete `date "+%Y-%m-%d %T"` --debug -d postgres > $BASE_PATH/results/log_delete2 2>&1 -pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show2 2>&1 -echo "# of deleted backups" -grep -c DELETED $BASE_PATH/results/log_show2 -pg_rman -p $TEST_PGPORT show timeline `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show_timeline_4 2>&1 - -# cleanup -pg_ctl stop -m immediate > /dev/null 2>&1 - +#!/bin/sh + +BASE_PATH=`pwd` +export PGDATA=$BASE_PATH/results/sample_database + +export BACKUP_PATH=$BASE_PATH/results/sample_backup2 +export ARCLOG_PATH=$BASE_PATH/results/arclog +export SRVLOG_PATH=$PGDATA/pg_log +export COMPRESS_DATA=YES +XLOG_PATH=$PGDATA/pg_xlog +TBLSPC_PATH=$BASE_PATH/results/tblspc + +# Port used for test database cluster +TEST_PGPORT=54321 + +# configuration +SCALE=1 +DURATION=10 +ISOLATE_SRVLOG=0 +ISOLATE_WAL=0 + +while [ $# -gt 0 ]; do + case $1 in + "-s") + ISOLATE_SRVLOG=1 + shift + ;; + "-w") + ISOLATE_WAL=1 + shift + ;; + "-d") + DURATION=`expr $2 + 0` + if [ $? -ne 0 ]; then + echo "invalid duration" + exit 1 + fi + shift 2 + ;; + "-s") + SCALE=`expr $2 + 0` + if [ $? -ne 0 ]; then + echo "invalid scale" + exit 1 + fi + shift 2 + ;; + *) + shift + ;; + esac +done + +# delete old database cluster +pg_ctl stop -m immediate > /dev/null 2>&1 +rm -rf $PGDATA +rm -rf $BASE_PATH/results/pg_xlog +rm -rf $BASE_PATH/results/srvlog +rm -rf $ARCLOG_PATH +rm -rf $SRVLOG_PATH +rm -rf $TBLSPC_PATH + +# create new backup catalog +rm -rf $BACKUP_PATH +pg_rman init -B $BACKUP_PATH --quiet + +# create default configuration file +cat << EOF > $BACKUP_PATH/pg_rman.ini + # comment + BACKUP_MODE = F # comment +EOF + +# create new database cluster +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 + +mkdir -p $ARCLOG_PATH +mkdir -p $TBLSPC_PATH + +# determine serverlog directory +if [ "$ISOLATE_SRVLOG" -ne 0 ]; then + export SRVLOG_PATH=$BASE_PATH/results/srvlog + echo "log_directory = '$SRVLOG_PATH'" >> $PGDATA/postgresql.conf + mkdir -p $SRVLOG_PATH +else + export SRVLOG_PATH=$PGDATA/pg_log + echo "log_directory = 'pg_log'" >> $PGDATA/postgresql.conf +fi + +# isolate online WAL +if [ "$ISOLATE_WAL" -ne 0 ]; then + XLOG_PATH=$BASE_PATH/results/pg_xlog + mv $PGDATA/pg_xlog $XLOG_PATH + ln -s $XLOG_PATH $PGDATA/pg_xlog +fi + +# start PostgreSQL +pg_ctl start -w -t 3600 > /dev/null 2>&1 + +# create tablespace and database for pgbench +mkdir -p $TBLSPC_PATH/pgbench +psql -p $TEST_PGPORT 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" +grep -c DELETED $BASE_PATH/results/log_show_d_1 + +pgbench -p $TEST_PGPORT -i -s $SCALE pgbench > $BASE_PATH/results/pgbench.log 2>&1 + +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 -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 -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 +pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show0 2>&1 +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 -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 -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" +pgbench -p $TEST_PGPORT -T $DURATION -c 10 pgbench >> $BASE_PATH/results/pgbench.log 2>&1 & +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 > $BASE_PATH/results/dump_before.sql + +# revert to crushed cluster +pg_ctl stop > /dev/null 2>&1 +rm -rf $PGDATA +mv $PGDATA.bak $PGDATA + +# validate all backup +pg_rman validate `date +%Y` --verbose > $BASE_PATH/results/log_validate2 2>&1 + +# restore check with pg_rman +pg_rman restore -! --verbose --check > $BASE_PATH/results/log_restore_check_1 2>&1 + +# restore with pg_rman +CUR_TLI=`pg_controldata | grep TimeLineID | awk '{print $4}'` +pg_rman restore -! --verbose > $BASE_PATH/results/log_restore1_1 2>&1 +CUR_TLI_R=`grep "current timeline ID = " $BASE_PATH/results/log_restore1_1 | awk '{print $5}'` +TARGET_TLI=`grep "target timeline ID = " $BASE_PATH/results/log_restore1_1 | awk '{print $5}'` +if [ "$CUR_TLI" != "$CUR_TLI_R" -o "$CUR_TLI" != "$CUR_TLI_R" ]; then + echo "failed: bad timeline ID" CUR_TLI=$CUR_TLI CUR_TLI_R=$CUR_TLI_R +fi + +# Backup of online-WAL and serverlog. +echo "diff files in BACKUP_PATH/backup/pg_xlog" +diff -r $PGDATA/pg_xlog $BACKUP_PATH/backup/pg_xlog +echo "# of files in BACKUP_PATH/backup/srvlog" +find $BACKUP_PATH/backup/srvlog -type f | wc -l + +# recovery database +pg_ctl start -w -t 3600 > /dev/null 2>&1 + +# re-restore with pg_rman +pg_ctl stop -m immediate > /dev/null 2>&1 + +# restore check with pg_rman +pg_rman restore -! --verbose --check > $BASE_PATH/results/log_restore_check_2 2>&1 + +CUR_TLI=`pg_controldata | grep TimeLineID | awk '{print $4}'` +pg_rman restore -! --verbose > $BASE_PATH/results/log_restore1_2 2>&1 +CUR_TLI_R=`grep "current timeline ID = " $BASE_PATH/results/log_restore1_2 | awk '{print $5}'` +TARGET_TLI=`grep "target timeline ID = " $BASE_PATH/results/log_restore1_2 | awk '{print $5}'` +if [ "$CUR_TLI" != "$CUR_TLI_R" -o "$CUR_TLI" != "$CUR_TLI_R" ]; then + echo "failed: bad timeline ID" CUR_TLI=$CUR_TLI CUR_TLI_R=$CUR_TLI_R +fi + +# Backup of online-WAL and serverlog. +echo "diff files in BACKUP_PATH/backup/pg_xlog" +diff -r $PGDATA/pg_xlog $BACKUP_PATH/backup/pg_xlog +echo "# of files in BACKUP_PATH/backup/srvlog" +find $BACKUP_PATH/backup/srvlog -type f | wc -l + +# re-recovery database +pg_ctl start -w -t 3600 > /dev/null 2>&1 + +# compare recovery results +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 +# 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 -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" +find $BACKUP_PATH/backup/pg_xlog -type f | wc -l +echo "# of files in BACKUP_PATH/backup/srvlog" +find $BACKUP_PATH/backup/srvlog -type f | wc -l + +# Symbolic links in $ARCLOG_PATH should be deleted. +echo "# of symbolic links in ARCLOG_PATH" +find $ARCLOG_PATH -type l | wc -l + +# timeline history files are backed up. +echo "# of files in BACKUP_PATH/timeline_history" +find $BACKUP_PATH/timeline_history -type f | wc -l + +# restore with pg_rman +pg_ctl stop -m immediate > /dev/null 2>&1 + +# restore check with pg_rman +pg_rman restore -! --verbose --check > $BASE_PATH/results/log_restore_check_3 2>&1 + +CUR_TLI=`pg_controldata | grep TimeLineID | awk '{print $4}'` +pg_rman restore -! --recovery-target-xid $target_xid --recovery-target-inclusive false --verbose > $BASE_PATH/results/log_restore2 2>&1 +CUR_TLI_R=`grep "current timeline ID = " $BASE_PATH/results/log_restore2 | awk '{print $5}'` +TARGET_TLI=`grep "target timeline ID = " $BASE_PATH/results/log_restore2 | awk '{print $5}'` +if [ "$CUR_TLI" != "$CUR_TLI_R" -o "$CUR_TLI" != "$CUR_TLI_R" ]; then + echo "failed: bad timeline ID" CUR_TLI=$CUR_TLI CUR_TLI_R=$CUR_TLI_R +fi +echo "# of recovery target option in recovery.conf" +grep -c "recovery_target_" $PGDATA/recovery.conf + +# recovery database +pg_ctl start -w -t 3600 > /dev/null 2>&1 + +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 +pg_rman -p $TEST_PGPORT show timeline --verbose -a -d postgres > $BASE_PATH/results/log_show_timeline_1 2>&1 +pg_rman -p $TEST_PGPORT show timeline `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show_timeline_2 2>&1 +pg_rman -p $TEST_PGPORT show timeline `date +%Y` --verbose -d postgres > $BASE_PATH/results/log_show_timeline_3 2>&1 +echo "# of deleted backups (show all)" +grep -c DELETED $BASE_PATH/results/log_show_timeline_2 +echo "# of deleted backups" +grep -c DELETED $BASE_PATH/results/log_show_timeline_3 + +echo "delete backup" +pg_rman -p $TEST_PGPORT delete --debug -d postgres > $BASE_PATH/results/log_delete1 2>&1 +pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show1 2>&1 +echo "# of deleted backups" +grep -c DELETED $BASE_PATH/results/log_show1 +pg_rman -p $TEST_PGPORT delete `date "+%Y-%m-%d %T"` --debug -d postgres > $BASE_PATH/results/log_delete2 2>&1 +pg_rman -p $TEST_PGPORT show `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show2 2>&1 +echo "# of deleted backups" +grep -c DELETED $BASE_PATH/results/log_show2 +pg_rman -p $TEST_PGPORT show timeline `date +%Y` -a --verbose -d postgres > $BASE_PATH/results/log_show_timeline_4 2>&1 + +# cleanup +pg_ctl stop -m immediate > /dev/null 2>&1 + diff --git a/sql/init.sql b/sql/init.sql index 9e6d02ff..6a52e990 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -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 $? diff --git a/sql/option.sh b/sql/option.sh index d0c3f001..88534db3 100644 --- a/sql/option.sh +++ b/sql/option.sh @@ -1,80 +1,80 @@ -#!/bin/sh - -#============================================================================ -# This is a test script for option test of pg_rman. -#============================================================================ - -BASE_PATH=`pwd` - -# Clear environment variables used by pg_rman except $PGDATA. -# List of environment variables is defined in catalog.c. -unset BACKUP_PATH -unset ARCLOG_PATH -unset SRVLOG_PATH -unset BACKUP_MODE -unset COMPRESS_DATA -unset KEEP_ARCLOG_DAYS -unset KEEP_DATA_GENERATIONS -unset KEEP_DATA_DAYS -unset KEEP_SRVLOG_FILES -unset KEEP_SRVLOG_DAYS - -export PGDATA=$BASE_PATH/results/sample_database - -# Note: not exported -BACKUP_PATH=$BASE_PATH/results/sample_backup2 - -# Setup backup catalog for backup test. -rm -rf $BACKUP_PATH -cp -rp data/sample_backup $BACKUP_PATH - -# general option -pg_rman --help -pg_rman --version - -# backup option -# required arguments check -pg_rman backup --verbose -pg_rman backup --verbose -B $BACKUP_PATH -pg_rman backup --verbose -B $BACKUP_PATH -b f -pg_rman backup --verbose -B $BACKUP_PATH -b i -pg_rman backup --verbose -B $BACKUP_PATH -b a - -# bad arguments check -pg_rman backup --verbose -B $BACKUP_PATH -b bad - -# delete or validate requires DATE -pg_rman delete -B $BACKUP_PATH -pg_rman validate -B $BACKUP_PATH - -# invalid configuration file check -echo " = INFINITE" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "BACKUP_MODE= " > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "BACKUP_MODE = F#S" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "BACKUP_MODE = F #comment A" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "BACKUP_MODE=B" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "COMPRESS_DATA=FOO" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "KEEP_ARCLOG_FILES=YES" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "TIMELINEID=-1" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "BACKUP_TARGETS=F" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH -echo "BACKUP_MODE='F''\'\\\F'" > $BACKUP_PATH/pg_rman.ini -pg_rman backup --verbose -B $BACKUP_PATH - -# configuration priorityfile check -echo "BACKUP_MODE=ENV_PATH" > $BACKUP_PATH/pg_rman.ini -mkdir $BACKUP_PATH/conf_path -echo "BACKUP_PATH=$BACKUP_PATH/conf_path" > $BACKUP_PATH/pg_rman.conf -echo "BACKUP_MODE=CONF_PATH" > $BACKUP_PATH/conf_path/pg_rman.ini -mkdir $BACKUP_PATH/comm_path -echo "BACKUP_MODE=COMM_PATH" > $BACKUP_PATH/comm_path/pg_rman.ini -export BACKUP_PATH=$BACKUP_PATH -pg_rman backup --verbose +#!/bin/sh + +#============================================================================ +# This is a test script for option test of pg_rman. +#============================================================================ + +BASE_PATH=`pwd` + +# Clear environment variables used by pg_rman except $PGDATA. +# List of environment variables is defined in catalog.c. +unset BACKUP_PATH +unset ARCLOG_PATH +unset SRVLOG_PATH +unset BACKUP_MODE +unset COMPRESS_DATA +unset KEEP_ARCLOG_DAYS +unset KEEP_DATA_GENERATIONS +unset KEEP_DATA_DAYS +unset KEEP_SRVLOG_FILES +unset KEEP_SRVLOG_DAYS + +export PGDATA=$BASE_PATH/results/sample_database + +# Note: not exported +BACKUP_PATH=$BASE_PATH/results/sample_backup2 + +# Setup backup catalog for backup test. +rm -rf $BACKUP_PATH +cp -rp data/sample_backup $BACKUP_PATH + +# general option +pg_rman --help +pg_rman --version + +# backup option +# required arguments check +pg_rman backup --verbose +pg_rman backup --verbose -B $BACKUP_PATH +pg_rman backup --verbose -B $BACKUP_PATH -b f +pg_rman backup --verbose -B $BACKUP_PATH -b i +pg_rman backup --verbose -B $BACKUP_PATH -b a + +# bad arguments check +pg_rman backup --verbose -B $BACKUP_PATH -b bad + +# delete or validate requires DATE +pg_rman delete -B $BACKUP_PATH +pg_rman validate -B $BACKUP_PATH + +# invalid configuration file check +echo " = INFINITE" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "BACKUP_MODE= " > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "BACKUP_MODE = F#S" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "BACKUP_MODE = F #comment A" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "BACKUP_MODE=B" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "COMPRESS_DATA=FOO" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "KEEP_ARCLOG_FILES=YES" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "TIMELINEID=-1" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "BACKUP_TARGETS=F" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH +echo "BACKUP_MODE='F''\'\\\F'" > $BACKUP_PATH/pg_rman.ini +pg_rman backup --verbose -B $BACKUP_PATH + +# configuration priorityfile check +echo "BACKUP_MODE=ENV_PATH" > $BACKUP_PATH/pg_rman.ini +mkdir $BACKUP_PATH/conf_path +echo "BACKUP_PATH=$BACKUP_PATH/conf_path" > $BACKUP_PATH/pg_rman.conf +echo "BACKUP_MODE=CONF_PATH" > $BACKUP_PATH/conf_path/pg_rman.ini +mkdir $BACKUP_PATH/comm_path +echo "BACKUP_MODE=COMM_PATH" > $BACKUP_PATH/comm_path/pg_rman.ini +export BACKUP_PATH=$BACKUP_PATH +pg_rman backup --verbose diff --git a/sql/show_validate.sql b/sql/show_validate.sql index 77e595f6..af7b2be1 100644 --- a/sql/show_validate.sql +++ b/sql/show_validate.sql @@ -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 diff --git a/util.c b/util.c index d57310eb..36fccdce 100644 --- a/util.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/utils.c b/utils.c index b89e875e..ba2acff5 100644 --- a/utils.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/validate.c b/validate.c index 1e874a3d..2df83759 100644 --- a/validate.c +++ b/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 * diff --git a/verify.c b/verify.c index af276b02..c4525811 100644 --- a/verify.c +++ b/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 * *------------------------------------------------------------------------- */ diff --git a/xlog.c b/xlog.c index 412d50a5..f6d36200 100644 --- a/xlog.c +++ b/xlog.c @@ -1,124 +1,127 @@ -/*------------------------------------------------------------------------- - * - * xlog.c: Parse WAL files. - * - * Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION - * - *------------------------------------------------------------------------- - */ - -#include "pg_rman.h" - -#include -#include -#include -#include - -#if PG_VERSION_NUM >= 80400 -typedef unsigned long Datum; -typedef struct MemoryContextData *MemoryContext; -#endif - -#include "access/xlog_internal.h" - -#define XLOG_PAGE_MAGIC_v80 0xD05C /* 8.0 */ -#define XLOG_PAGE_MAGIC_v81 0xD05D /* 8.1 */ -#define XLOG_PAGE_MAGIC_v82 0xD05E /* 8.2 */ -#define XLOG_PAGE_MAGIC_v83 0xD062 /* 8.3 */ -#define XLOG_PAGE_MAGIC_v84 0xD063 /* 8.4 */ -#define XLOG_PAGE_MAGIC_v90 0xD064 /* 9.0 */ - -/* - * XLogLongPageHeaderData is modified in 8.3, but the layout is compatible - * except xlp_xlog_blcksz. - */ -typedef union XLogPage -{ - XLogPageHeaderData header; - XLogLongPageHeaderData lheader; - char data[XLOG_BLCKSZ]; -} XLogPage; - -/* - * Return whether the file is a WAL segment or not. - * based on ValidXLOGHeader() in src/backend/access/transam/xlog.c. - */ -bool -xlog_is_complete_wal(const pgFile *file, int server_version) -{ - FILE *fp; - XLogPage page; - uint16 xlog_page_magic; - - fp = fopen(file->path, "r"); - if (!fp) - return false; - if (fread(&page, 1, sizeof(page), fp) != XLOG_BLCKSZ) - { - fclose(fp); - return false; - } - fclose(fp); - - /* xlog_page_magic from server version */ - if (server_version < 80000) - return false; /* never happen */ - else if (server_version < 80100) - xlog_page_magic = XLOG_PAGE_MAGIC_v80; - else if (server_version < 80200) - xlog_page_magic = XLOG_PAGE_MAGIC_v81; - else if (server_version < 80300) - xlog_page_magic = XLOG_PAGE_MAGIC_v82; - else if (server_version < 80400) - xlog_page_magic = XLOG_PAGE_MAGIC_v83; - else if (server_version < 90000) - xlog_page_magic = XLOG_PAGE_MAGIC_v84; - else if (server_version < 90100) - xlog_page_magic = XLOG_PAGE_MAGIC_v90; - else - return false; /* not supported */ - - /* check header */ - if (page.header.xlp_magic != xlog_page_magic) - return false; - if ((page.header.xlp_info & ~XLP_ALL_FLAGS) != 0) - return false; - if ((page.header.xlp_info & XLP_LONG_HEADER) == 0) - return false; - if (page.lheader.xlp_seg_size != XLogSegSize) - return false; - if (server_version >= 80300 && page.lheader.xlp_xlog_blcksz != XLOG_BLCKSZ) - return false; - - /* - * check size (actual file size, not backup file size) - * TODO: Support pre-compressed xlog. They might have different file sizes. - */ - if (file->size != XLogSegSize) - return false; - - return true; -} - -bool -xlog_logfname2lsn(const char *logfname, XLogRecPtr *lsn) -{ - uint32 tli; - - if (sscanf(logfname, "%08X%08X%08X", - &tli, &lsn->xlogid, &lsn->xrecoff) != 3) - return false; - - lsn->xrecoff *= XLogSegSize; - return true; -} - -/* - * based on XLogFileName() in xlog_internal.h - */ -void -xlog_fname(char *fname, size_t len, TimeLineID tli, XLogRecPtr *lsn) -{ - snprintf(fname, len, "%08X%08X%08X", tli, - lsn->xlogid, lsn->xrecoff / XLogSegSize); -} +/*------------------------------------------------------------------------- + * + * xlog.c: Parse WAL files. + * + * Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION + * + *------------------------------------------------------------------------- + */ + +#include "pg_rman.h" + +#include +#include +#include +#include + +#if PG_VERSION_NUM >= 80400 +typedef unsigned long Datum; +typedef struct MemoryContextData *MemoryContext; +#endif + +#include "access/xlog_internal.h" + +#define XLOG_PAGE_MAGIC_v80 0xD05C /* 8.0 */ +#define XLOG_PAGE_MAGIC_v81 0xD05D /* 8.1 */ +#define XLOG_PAGE_MAGIC_v82 0xD05E /* 8.2 */ +#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 + * except xlp_xlog_blcksz. + */ +typedef union XLogPage +{ + XLogPageHeaderData header; + XLogLongPageHeaderData lheader; + char data[XLOG_BLCKSZ]; +} XLogPage; + +/* + * Return whether the file is a WAL segment or not. + * based on ValidXLOGHeader() in src/backend/access/transam/xlog.c. + */ +bool +xlog_is_complete_wal(const pgFile *file, int server_version) +{ + FILE *fp; + XLogPage page; + uint16 xlog_page_magic; + + fp = fopen(file->path, "r"); + if (!fp) + return false; + if (fread(&page, 1, sizeof(page), fp) != XLOG_BLCKSZ) + { + fclose(fp); + return false; + } + fclose(fp); + + /* xlog_page_magic from server version */ + if (server_version < 80000) + return false; /* never happen */ + else if (server_version < 80100) + xlog_page_magic = XLOG_PAGE_MAGIC_v80; + else if (server_version < 80200) + xlog_page_magic = XLOG_PAGE_MAGIC_v81; + else if (server_version < 80300) + xlog_page_magic = XLOG_PAGE_MAGIC_v82; + else if (server_version < 80400) + xlog_page_magic = XLOG_PAGE_MAGIC_v83; + else if (server_version < 90000) + 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 */ + + /* check header */ + if (page.header.xlp_magic != xlog_page_magic) + return false; + if ((page.header.xlp_info & ~XLP_ALL_FLAGS) != 0) + return false; + if ((page.header.xlp_info & XLP_LONG_HEADER) == 0) + return false; + if (page.lheader.xlp_seg_size != XLogSegSize) + return false; + if (server_version >= 80300 && page.lheader.xlp_xlog_blcksz != XLOG_BLCKSZ) + return false; + + /* + * check size (actual file size, not backup file size) + * TODO: Support pre-compressed xlog. They might have different file sizes. + */ + if (file->size != XLogSegSize) + return false; + + return true; +} + +bool +xlog_logfname2lsn(const char *logfname, XLogRecPtr *lsn) +{ + uint32 tli; + + if (sscanf(logfname, "%08X%08X%08X", + &tli, &lsn->xlogid, &lsn->xrecoff) != 3) + return false; + + lsn->xrecoff *= XLogSegSize; + return true; +} + +/* + * based on XLogFileName() in xlog_internal.h + */ +void +xlog_fname(char *fname, size_t len, TimeLineID tli, XLogRecPtr *lsn) +{ + snprintf(fname, len, "%08X%08X%08X", tli, + lsn->xlogid, lsn->xrecoff / XLogSegSize); +}