mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2024-11-25 09:01:48 +02:00
Clean up the snapshot related stuff
This is not really part of the core of pg_rman, rather better to focus on incremental backup or stuff like that.
This commit is contained in:
parent
ebe2166379
commit
b92d722bdb
230
backup.c
230
backup.c
@ -57,14 +57,6 @@ static void delete_online_wal_backup(void);
|
||||
|
||||
static bool dirExists(const char *path);
|
||||
|
||||
static void execute_freeze(void);
|
||||
static void execute_unfreeze(void);
|
||||
static void execute_split(parray *tblspc_list);
|
||||
static void execute_resync(void);
|
||||
static void execute_mount(parray *tblspcmp_list);
|
||||
static void execute_umount(void);
|
||||
static void execute_script(const char *mode, bool is_cleanup, parray *output);
|
||||
static void snapshot_cleanup(bool fatal, void *userdata);
|
||||
static void add_files(parray *files, const char *root, bool add_root, bool is_pgdata);
|
||||
static int strCompare(const void *str1, const void *str2);
|
||||
static void create_file_list(parray *files, const char *root, const char *prefix, bool is_append);
|
||||
@ -241,20 +233,6 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
|
||||
for (i = 0; pgdata_exclude[i]; i++); /* find first empty slot */
|
||||
pgdata_exclude[i] = PG_TBLSPC_DIR;
|
||||
|
||||
/* set the error processing for the snapshot */
|
||||
pgut_atexit_push(snapshot_cleanup, cleanup_list);
|
||||
|
||||
/* create snapshot volume */
|
||||
if (!check)
|
||||
{
|
||||
/* freeze I/O of the file-system */
|
||||
execute_freeze();
|
||||
/* create the snapshot, and obtain the name of TABLESPACE backup from snapshot */
|
||||
execute_split(tblspc_list);
|
||||
/* unfreeze I/O of the file-system */
|
||||
execute_unfreeze();
|
||||
}
|
||||
|
||||
/*
|
||||
* when DB cluster is not contained in the backup from the snapshot,
|
||||
* DB cluster is added to the backup file list from non-snapshot.
|
||||
@ -315,10 +293,6 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
|
||||
/* create file list of non-snapshot objects */
|
||||
create_file_list(files, pgdata, NULL, false);
|
||||
|
||||
/* mount snapshot volume to file-system, and obtain that mounted directory */
|
||||
if (!check)
|
||||
execute_mount(tblspcmp_list);
|
||||
|
||||
/* backup files from snapshot volume */
|
||||
for (i = 0; i < parray_num(tblspcmp_list); i++)
|
||||
{
|
||||
@ -414,17 +388,7 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
|
||||
parray_walk(tblspcmp_list, free);
|
||||
parray_free(tblspcmp_list);
|
||||
|
||||
/* snapshot became unnecessary, annul the snapshot */
|
||||
if (!check)
|
||||
{
|
||||
/* unmount directory of mounted snapshot volume */
|
||||
execute_umount();
|
||||
/* annul the snapshot */
|
||||
execute_resync();
|
||||
}
|
||||
|
||||
/* unset the error processing for the snapshot */
|
||||
pgut_atexit_pop(snapshot_cleanup, cleanup_list);
|
||||
/* don't use 'parray_walk'. element of parray not allocate memory by malloc */
|
||||
parray_free(cleanup_list);
|
||||
PQclear(tblspc_res);
|
||||
@ -1557,200 +1521,6 @@ delete_arclog_link(void)
|
||||
parray_free(files);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the command 'freeze' of snapshot-script.
|
||||
* When the command ends normally, 'unfreeze' is added to the cleanup list.
|
||||
*/
|
||||
static void
|
||||
execute_freeze(void)
|
||||
{
|
||||
/* append 'unfreeze' command to cleanup list */
|
||||
parray_append(cleanup_list, SNAPSHOT_UNFREEZE);
|
||||
|
||||
/* execute 'freeze' command */
|
||||
execute_script(SNAPSHOT_FREEZE, false, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the command 'unfreeze' of snapshot-script.
|
||||
* Remove 'unfreeze' from the cleanup list before executing the command
|
||||
* when 'unfreeze' is included in the cleanup list.
|
||||
*/
|
||||
static void
|
||||
execute_unfreeze(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* remove 'unfreeze' command from cleanup list */
|
||||
for (i = 0; i < parray_num(cleanup_list); i++)
|
||||
{
|
||||
char *mode;
|
||||
|
||||
mode = (char *) parray_get(cleanup_list, i);
|
||||
if (strcmp(mode,SNAPSHOT_UNFREEZE) == 0)
|
||||
{
|
||||
parray_remove(cleanup_list, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* execute 'unfreeze' command */
|
||||
execute_script(SNAPSHOT_UNFREEZE, false, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the command 'split' of snapshot-script.
|
||||
* When the command ends normally, 'resync' is added to the cleanup list.
|
||||
*/
|
||||
static void
|
||||
execute_split(parray *tblspc_list)
|
||||
{
|
||||
/* append 'resync' command to cleanup list */
|
||||
parray_append(cleanup_list, SNAPSHOT_RESYNC);
|
||||
|
||||
/* execute 'split' command */
|
||||
execute_script(SNAPSHOT_SPLIT, false, tblspc_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the command 'resync' of snapshot-script.
|
||||
* Remove 'resync' from the cleanup list before executing the command
|
||||
* when 'resync' is included in the cleanup list.
|
||||
*/
|
||||
static void
|
||||
execute_resync(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* remove 'resync' command from cleanup list */
|
||||
for (i = 0; i < parray_num(cleanup_list); i++)
|
||||
{
|
||||
char *mode;
|
||||
|
||||
mode = (char *) parray_get(cleanup_list, i);
|
||||
if (strcmp(mode, SNAPSHOT_RESYNC) == 0)
|
||||
{
|
||||
parray_remove(cleanup_list, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* execute 'resync' command */
|
||||
execute_script(SNAPSHOT_RESYNC, false, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the command 'mount' of snapshot-script.
|
||||
* When the command ends normally, 'umount' is added to the cleanup list.
|
||||
*/
|
||||
static void
|
||||
execute_mount(parray *tblspcmp_list)
|
||||
{
|
||||
/* append 'umount' command to cleanup list */
|
||||
parray_append(cleanup_list, SNAPSHOT_UMOUNT);
|
||||
|
||||
/* execute 'mount' command */
|
||||
execute_script(SNAPSHOT_MOUNT, false, tblspcmp_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the command 'umount' of snapshot-script.
|
||||
* Remove 'umount' from the cleanup list before executing the command
|
||||
* when 'umount' is included in the cleanup list.
|
||||
*/
|
||||
static void
|
||||
execute_umount(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* remove 'umount' command from cleanup list */
|
||||
for (i = 0; i < parray_num(cleanup_list); i++)
|
||||
{
|
||||
char *mode = (char *) parray_get(cleanup_list, i);
|
||||
|
||||
if (strcmp(mode, SNAPSHOT_UMOUNT) == 0)
|
||||
{
|
||||
parray_remove(cleanup_list, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* execute 'umount' command */
|
||||
execute_script(SNAPSHOT_UMOUNT, false, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the snapshot-script in the specified mode.
|
||||
* A standard output of snapshot-script is stored in the array given to the parameter.
|
||||
* If is_cleanup is TRUE, processing is continued.
|
||||
*/
|
||||
static void
|
||||
execute_script(const char *mode, bool is_cleanup, parray *output)
|
||||
{
|
||||
char ss_script[MAXPGPATH];
|
||||
char command[1024];
|
||||
char fline[2048];
|
||||
int num;
|
||||
FILE *out;
|
||||
parray *lines;
|
||||
|
||||
/* obtain the path of snapshot-script. */
|
||||
join_path_components(ss_script, backup_path, SNAPSHOT_SCRIPT_FILE);
|
||||
snprintf(command, sizeof(command),
|
||||
"%s %s %s", ss_script, mode, is_cleanup ? "cleanup" : "");
|
||||
|
||||
/* execute snapshot-script */
|
||||
out = popen(command, "r");
|
||||
if (out == NULL)
|
||||
elog(ERROR_SYSTEM, _("could not execute snapshot-script: %s\n"), strerror(errno));
|
||||
|
||||
/* read STDOUT and store into the array each line */
|
||||
lines = parray_new();
|
||||
while (fgets(fline, sizeof(fline), out) != NULL)
|
||||
{
|
||||
/* remove line separator */
|
||||
if (fline[strlen(fline) - 1] == '\n')
|
||||
fline[strlen(fline) - 1] = '\0';
|
||||
parray_append(lines, pgut_strdup(fline));
|
||||
}
|
||||
pclose(out);
|
||||
|
||||
/*
|
||||
* status of the command is obtained from the last element of the array
|
||||
* if last element is not 'SUCCESS', that means ERROR.
|
||||
*/
|
||||
num = parray_num(lines);
|
||||
if (num <= 0 || strcmp((char *) parray_get(lines, num - 1), "SUCCESS") != 0)
|
||||
elog(is_cleanup ? WARNING : ERROR_SYSTEM, _("snapshot-script failed: %s"), mode);
|
||||
|
||||
/* if output is not NULL, concat array. */
|
||||
if (output)
|
||||
{
|
||||
parray_remove(lines, num -1); /* remove last element, that is command status */
|
||||
parray_concat(output, lines);
|
||||
}
|
||||
/* if output is NULL, clear directory list */
|
||||
else
|
||||
{
|
||||
parray_walk(lines, free);
|
||||
parray_free(lines);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the unnecessary object created by snapshot-script.
|
||||
* The command necessary for the deletion is given from the parameter.
|
||||
* When the error occurs, this function is called.
|
||||
*/
|
||||
static void
|
||||
snapshot_cleanup(bool fatal, void *userdata)
|
||||
{
|
||||
parray *cleanup_list;
|
||||
int i;
|
||||
|
||||
/* Execute snapshot-script for cleanup */
|
||||
cleanup_list = (parray *) userdata;
|
||||
for (i = parray_num(cleanup_list) - 1; i >= 0; i--)
|
||||
execute_script((char *) parray_get(cleanup_list, i), true, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append files to the backup list array.
|
||||
*/
|
||||
|
@ -1,306 +0,0 @@
|
||||
#!/bin/sh
|
||||
#############################################################################
|
||||
# Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||
#############################################################################
|
||||
|
||||
CMD_SUDO="/usr/bin/sudo"
|
||||
CMD_LVCREATE="${CMD_SUDO} /usr/sbin/lvcreate"
|
||||
CMD_LVREMOVE="${CMD_SUDO} /usr/sbin/lvremove"
|
||||
CMD_MOUNT="${CMD_SUDO} /bin/mount"
|
||||
CMD_UMOUNT="${CMD_SUDO} /bin/umount"
|
||||
|
||||
INFO=-2
|
||||
WARNING=-1
|
||||
ERROR=0
|
||||
|
||||
#
|
||||
# Please set the information necessary for the snapshot acquisition
|
||||
# to each array.
|
||||
#
|
||||
# The following arrays are one sets.
|
||||
#
|
||||
# SNAPSHOT_NAME .... name for snapshot volume
|
||||
# SNAPSHOT_SIZE .... size to allocate for snapshot volume
|
||||
# SNAPSHOT_VG ...... volume group to which logical volume to create snapshot belongs
|
||||
# SNAPSHOT_LV ...... logical volume to create snapshot
|
||||
# SNAPSHOT_MOUNT ... mount point to file-system of snapshot volume
|
||||
#
|
||||
# increase and decrease the slot in proportion to the number of acquisition
|
||||
# of snapshots.
|
||||
#
|
||||
# example:
|
||||
#
|
||||
# SNAPSHOT_NAME[0]="snap00"
|
||||
# SNAPSHOT_SIZE[0]="2G"
|
||||
# SNAPSHOT_VG[0]="/dev/VolumeGroup00"
|
||||
# SNAPSHOT_LV[0]="/dev/VolumeGroup00/LogicalVolume00"
|
||||
# SNAPSHOT_MOUNT[0]="/mnt/pgdata"
|
||||
#
|
||||
# SNAPSHOT_NAME[1]="snap01"
|
||||
# SNAPSHOT_SIZE[1]="2G"
|
||||
# SNAPSHOT_VG[1]="/dev/VolumeGroup00"
|
||||
# SNAPSHOT_LV[1]="/dev/VolumeGroup00/LogicalVolume01"
|
||||
# SNAPSHOT_MOUNT[1]="/mnt/tblspc/account"
|
||||
#
|
||||
#SNAPSHOT_NAME[0]=""
|
||||
#SNAPSHOT_SIZE[0]=""
|
||||
#SNAPSHOT_VG[0]=""
|
||||
#SNAPSHOT_LV[0]=""
|
||||
#SNAPSHOT_MOUNT[0]=""
|
||||
|
||||
#
|
||||
# Please set the tablespace name and tablespace storage path in snapshot
|
||||
# to each array.
|
||||
#
|
||||
# The following arrays are one sets.
|
||||
#
|
||||
# SNAPSHOT_TBLSPC ........ name of tablespace in snapshot volume
|
||||
# SNAPSHOT_TBLSPC_DIR .... stored directory of tablespace in snapshot volume
|
||||
#
|
||||
# Note: set 'PG-DATA' to SNAPSHOT_TBLSPC when PGDATA in snapshot volume.
|
||||
#
|
||||
# increase and decrease the slot in proportion to the number of acquisition
|
||||
# of tablespace.
|
||||
#
|
||||
# example:
|
||||
#
|
||||
# SNAPSHOT_TBLSPC[0]="PG-DATA"
|
||||
# SNAPSHOT_TBLSPC_DIR[0]="/mnt/pgdata/pgdata"
|
||||
# SNAPSHOT_TBLSPC[1]="custom"
|
||||
# SNAPSHOT_TBLSPC_DIR[1]="/mnt/tblspc_custom/tblspc/custom"
|
||||
# SNAPSHOT_TBLSPC[2]="account"
|
||||
# SNAPSHOT_TBLSPC_DIR[2]="/mnt/tblspc_account/tblspc/account"
|
||||
#
|
||||
#SNAPSHOT_TBLSPC[0]=""
|
||||
#SNAPSHOT_TBLSPC_DIR[0]=""
|
||||
|
||||
#
|
||||
# argument of the command.
|
||||
# this variables are set by set_args().
|
||||
#
|
||||
ARGS_SS_NAME="" # SNAPSHOT_NAME[N]
|
||||
ARGS_SS_SIZE="" # SNAPSHOT_SIZE[N]
|
||||
ARGS_SS_VG="" # SNAPSHOT_VG[N]
|
||||
ARGS_SS_LV="" # SNAPSHOT_LV[N]
|
||||
ARGS_SS_MOUNT="" # SNAPSHOT_MOUNT[N]
|
||||
|
||||
|
||||
#
|
||||
# implement of interface 'freeze'.
|
||||
# don't remove this function even if there is no necessity.
|
||||
#
|
||||
function freeze()
|
||||
{
|
||||
# nothing to do
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# implement of interface 'unfreeze'.
|
||||
# don't remove this function even if there is no necessity.
|
||||
#
|
||||
function unfreeze()
|
||||
{
|
||||
# nothing to do
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# implement of interface 'split'.
|
||||
# create a snapshot volume from the setting of the specified slot.
|
||||
# don't remove this function even if there is no necessity.
|
||||
#
|
||||
function split()
|
||||
{
|
||||
local i=0
|
||||
|
||||
for ss_name in "${SNAPSHOT_NAME[@]}"
|
||||
do
|
||||
set_args "${ss_name}" "${SNAPSHOT_SIZE[${i}]}" "" "${SNAPSHOT_LV[${i}]}" ""
|
||||
execute_split
|
||||
i=$(expr ${i} + 1)
|
||||
done
|
||||
|
||||
# print tablespace name
|
||||
i=0
|
||||
for tblspc in "${SNAPSHOT_TBLSPC[@]}"
|
||||
do
|
||||
local tblspc="${SNAPSHOT_TBLSPC[${i}]}"
|
||||
|
||||
echo "${tblspc}"
|
||||
i=$(expr ${i} + 1)
|
||||
done
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# implement of interface 'resync'.
|
||||
# remove a snapshot volume from the setting of the specified slot.
|
||||
# don't remove this function even if there is no necessity.
|
||||
#
|
||||
function resync()
|
||||
{
|
||||
local i=0
|
||||
|
||||
for ss_name in "${SNAPSHOT_NAME[@]}"
|
||||
do
|
||||
set_args "${ss_name}" "" "${SNAPSHOT_VG[${i}]}" "" ""
|
||||
execute_resync
|
||||
i=$(expr ${i} + 1)
|
||||
done
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# implement of interface 'mount'.
|
||||
# create mount point of the snapshot volume to the file-system.
|
||||
# don't remove this function even if there is no necessity.
|
||||
#
|
||||
function mount()
|
||||
{
|
||||
local i=0
|
||||
|
||||
for ss_name in "${SNAPSHOT_NAME[@]}"
|
||||
do
|
||||
set_args "${ss_name}" "" "${SNAPSHOT_VG[${i}]}" "" "${SNAPSHOT_MOUNT[${i}]}"
|
||||
execute_mount
|
||||
i=$(expr ${i} + 1)
|
||||
done
|
||||
|
||||
# print tablespace name and stored directory
|
||||
i=0
|
||||
for tblspc in "${SNAPSHOT_TBLSPC[@]}"
|
||||
do
|
||||
local tblspc_mp="${SNAPSHOT_TBLSPC_DIR[${i}]}"
|
||||
|
||||
echo "${tblspc}=${tblspc_mp}"
|
||||
i=$(expr ${i} + 1)
|
||||
done
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# implement of interface 'umount'.
|
||||
# remove mount point of the snapshot volume from the file-system.
|
||||
# don't remove this function even if there is no necessity.
|
||||
#
|
||||
function umount()
|
||||
{
|
||||
for ss_mp in "${SNAPSHOT_MOUNT[@]}"
|
||||
do
|
||||
set_args "" "" "" "" "${ss_mp}"
|
||||
execute_umount
|
||||
done
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# create the snapshot volume.
|
||||
#
|
||||
function execute_split()
|
||||
{
|
||||
${CMD_LVCREATE} --snapshot --size=${ARGS_SS_SIZE} --name="${ARGS_SS_NAME}" "${ARGS_SS_LV}" > /dev/null
|
||||
[ ${?} -ne 0 ] && \
|
||||
print_log ${ERROR} "${CMD_LVCREATE} command failed: ${ARGS_SS_LV}"
|
||||
}
|
||||
|
||||
#
|
||||
# remove the snapshot volume.
|
||||
#
|
||||
function execute_resync()
|
||||
{
|
||||
${CMD_LVREMOVE} -f "${ARGS_SS_VG}/${ARGS_SS_NAME}" > /dev/null
|
||||
[ ${?} -ne 0 ] && \
|
||||
print_log ${ERROR} "${CMD_LVREMOVE} command failed: ${ARGS_SS_VG}/${ARGS_SS_NAME}"
|
||||
}
|
||||
|
||||
#
|
||||
# mount the snapshot volume to file-system.
|
||||
#
|
||||
function execute_mount()
|
||||
{
|
||||
${CMD_MOUNT} "${ARGS_SS_VG}/${ARGS_SS_NAME}" "${ARGS_SS_MOUNT}" > /dev/null
|
||||
[ ${?} -ne 0 ] && \
|
||||
print_log ${ERROR} "${CMD_MOUNT} command failed: ${ARGS_SS_MOUNT}"
|
||||
}
|
||||
|
||||
#
|
||||
# unmount the directory from file-system in snapshot volume.
|
||||
#
|
||||
function execute_umount()
|
||||
{
|
||||
${CMD_UMOUNT} "${ARGS_SS_MOUNT}" > /dev/null
|
||||
[ ${?} -ne 0 ] && \
|
||||
print_log ${ERROR} "${CMD_UMOUNT} command failed: ${ARGS_SS_MOUNT}"
|
||||
}
|
||||
|
||||
#
|
||||
# set argument of command to execute.
|
||||
#
|
||||
set_args()
|
||||
{
|
||||
ARGS_SS_NAME="${1}"
|
||||
ARGS_SS_SIZE="${2}"
|
||||
ARGS_SS_VG="${3}"
|
||||
ARGS_SS_LV="${4}"
|
||||
ARGS_SS_MOUNT="${5}"
|
||||
}
|
||||
|
||||
#
|
||||
# output the log message and abort the script when level <= ERROR
|
||||
#
|
||||
function print_log()
|
||||
{
|
||||
local level="${1}"
|
||||
local message="${2}"
|
||||
|
||||
# if cleanup enable change ERROR to WARNING
|
||||
[ -n "${cleanup}" -a ${level} -ge 0 ] && \
|
||||
level=${WARNING}
|
||||
|
||||
case "${level}" in
|
||||
${INFO} ) # INFO
|
||||
echo "INFO: ${message}" 1>&2
|
||||
;;
|
||||
${WARNING} ) # WARNING
|
||||
echo "WARNING: ${message}" 1>&2
|
||||
;;
|
||||
${ERROR} ) # ERROR
|
||||
echo "ERROR: ${message}" 1>&2
|
||||
;;
|
||||
esac
|
||||
[ ${level} -ge 0 ] && exit
|
||||
}
|
||||
|
||||
#
|
||||
# main
|
||||
#
|
||||
command="${1}"
|
||||
cleanup="${2}"
|
||||
|
||||
case "${command}" in
|
||||
"freeze" )
|
||||
freeze
|
||||
;;
|
||||
"unfreeze" )
|
||||
unfreeze
|
||||
;;
|
||||
"split" )
|
||||
split
|
||||
;;
|
||||
"resync" )
|
||||
resync
|
||||
;;
|
||||
"mount" )
|
||||
mount
|
||||
;;
|
||||
"umount" )
|
||||
umount
|
||||
;;
|
||||
* )
|
||||
print_log ${ERROR} "specified invalid command: ${command} (internal error)"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "SUCCESS"
|
||||
exit
|
Loading…
Reference in New Issue
Block a user