mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2024-11-24 08:52:38 +02:00
Implement remote backup though SSH
This commit is contained in:
parent
bf1c8797ae
commit
050d0150d0
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ PROGRAM = pg_probackup
|
||||
|
||||
# utils
|
||||
OBJS = src/utils/json.o src/utils/logger.o src/utils/parray.o \
|
||||
src/utils/pgut.o src/utils/thread.o
|
||||
src/utils/pgut.o src/utils/thread.o src/utils/remote.o src/utils/file.o
|
||||
|
||||
OBJS += src/archive.o src/backup.o src/catalog.o src/configure.o src/data.o \
|
||||
src/delete.o src/dir.o src/fetch.o src/help.o src/init.o src/merge.o \
|
||||
|
23
src/backup.c
23
src/backup.c
@ -22,6 +22,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils/thread.h"
|
||||
#include "utils/file.h"
|
||||
|
||||
#define PG_STOP_BACKUP_TIMEOUT 300
|
||||
|
||||
@ -572,7 +573,7 @@ do_backup_instance(void)
|
||||
if (stream_wal)
|
||||
{
|
||||
join_path_components(dst_backup_path, database_path, PG_XLOG_DIR);
|
||||
dir_create_dir(dst_backup_path, DIR_PERMISSION);
|
||||
fio_mkdir(dst_backup_path, DIR_PERMISSION, FIO_BACKUP_HOST);
|
||||
|
||||
stream_thread_arg.basedir = dst_backup_path;
|
||||
|
||||
@ -689,7 +690,7 @@ do_backup_instance(void)
|
||||
DATABASE_DIR);
|
||||
|
||||
join_path_components(dirpath, database_path, dir_name);
|
||||
dir_create_dir(dirpath, DIR_PERMISSION);
|
||||
fio_mkdir(dirpath, DIR_PERMISSION, FIO_BACKUP_HOST);
|
||||
}
|
||||
|
||||
/* setup threads */
|
||||
@ -1847,16 +1848,15 @@ pg_stop_backup(pgBackup *backup)
|
||||
|
||||
/* Write backup_label */
|
||||
join_path_components(backup_label, path, PG_BACKUP_LABEL_FILE);
|
||||
fp = fopen(backup_label, PG_BINARY_W);
|
||||
fp = fio_open(backup_label, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (fp == NULL)
|
||||
elog(ERROR, "can't open backup label file \"%s\": %s",
|
||||
backup_label, strerror(errno));
|
||||
|
||||
len = strlen(PQgetvalue(res, 0, 3));
|
||||
if (fwrite(PQgetvalue(res, 0, 3), 1, len, fp) != len ||
|
||||
fflush(fp) != 0 ||
|
||||
fsync(fileno(fp)) != 0 ||
|
||||
fclose(fp))
|
||||
if (fio_write(fp, PQgetvalue(res, 0, 3), len) != len ||
|
||||
fio_flush(fp) != 0 ||
|
||||
fio_close(fp))
|
||||
elog(ERROR, "can't write backup label file \"%s\": %s",
|
||||
backup_label, strerror(errno));
|
||||
|
||||
@ -1895,16 +1895,15 @@ pg_stop_backup(pgBackup *backup)
|
||||
char tablespace_map[MAXPGPATH];
|
||||
|
||||
join_path_components(tablespace_map, path, PG_TABLESPACE_MAP_FILE);
|
||||
fp = fopen(tablespace_map, PG_BINARY_W);
|
||||
fp = fio_open(tablespace_map, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (fp == NULL)
|
||||
elog(ERROR, "can't open tablespace map file \"%s\": %s",
|
||||
tablespace_map, strerror(errno));
|
||||
|
||||
len = strlen(val);
|
||||
if (fwrite(val, 1, len, fp) != len ||
|
||||
fflush(fp) != 0 ||
|
||||
fsync(fileno(fp)) != 0 ||
|
||||
fclose(fp))
|
||||
if (fio_write(fp, val, len) != len ||
|
||||
fio_flush(fp) != 0 ||
|
||||
fio_close(fp))
|
||||
elog(ERROR, "can't write tablespace map file \"%s\": %s",
|
||||
tablespace_map, strerror(errno));
|
||||
|
||||
|
@ -8,13 +8,14 @@
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "pg_probackup.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pg_probackup.h"
|
||||
#include "utils/file.h"
|
||||
|
||||
static const char *backupModes[] = {"", "PAGE", "PTRACK", "DELTA", "FULL"};
|
||||
static pgBackup *readBackupControlFile(const char *path);
|
||||
|
||||
@ -413,13 +414,13 @@ pgBackupCreateDir(pgBackup *backup)
|
||||
if (!dir_is_empty(path))
|
||||
elog(ERROR, "backup destination is not empty \"%s\"", path);
|
||||
|
||||
dir_create_dir(path, DIR_PERMISSION);
|
||||
fio_mkdir(path, DIR_PERMISSION, FIO_BACKUP_HOST);
|
||||
|
||||
/* create directories for actual backup files */
|
||||
for (i = 0; subdirs[i]; i++)
|
||||
{
|
||||
pgBackupGetPath(backup, path, lengthof(path), subdirs[i]);
|
||||
dir_create_dir(path, DIR_PERMISSION);
|
||||
fio_mkdir(path, DIR_PERMISSION, FIO_BACKUP_HOST);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -433,46 +434,46 @@ pgBackupWriteControl(FILE *out, pgBackup *backup)
|
||||
{
|
||||
char timestamp[100];
|
||||
|
||||
fprintf(out, "#Configuration\n");
|
||||
fprintf(out, "backup-mode = %s\n", pgBackupGetBackupMode(backup));
|
||||
fprintf(out, "stream = %s\n", backup->stream ? "true" : "false");
|
||||
fprintf(out, "compress-alg = %s\n",
|
||||
fio_printf(out, "#Configuration\n");
|
||||
fio_printf(out, "backup-mode = %s\n", pgBackupGetBackupMode(backup));
|
||||
fio_printf(out, "stream = %s\n", backup->stream ? "true" : "false");
|
||||
fio_printf(out, "compress-alg = %s\n",
|
||||
deparse_compress_alg(backup->compress_alg));
|
||||
fprintf(out, "compress-level = %d\n", backup->compress_level);
|
||||
fprintf(out, "from-replica = %s\n", backup->from_replica ? "true" : "false");
|
||||
fio_printf(out, "compress-level = %d\n", backup->compress_level);
|
||||
fio_printf(out, "from-replica = %s\n", backup->from_replica ? "true" : "false");
|
||||
|
||||
fprintf(out, "\n#Compatibility\n");
|
||||
fprintf(out, "block-size = %u\n", backup->block_size);
|
||||
fprintf(out, "xlog-block-size = %u\n", backup->wal_block_size);
|
||||
fprintf(out, "checksum-version = %u\n", backup->checksum_version);
|
||||
fio_printf(out, "\n#Compatibility\n");
|
||||
fio_printf(out, "block-size = %u\n", backup->block_size);
|
||||
fio_printf(out, "xlog-block-size = %u\n", backup->wal_block_size);
|
||||
fio_printf(out, "checksum-version = %u\n", backup->checksum_version);
|
||||
if (backup->program_version[0] != '\0')
|
||||
fprintf(out, "program-version = %s\n", backup->program_version);
|
||||
fio_printf(out, "program-version = %s\n", backup->program_version);
|
||||
if (backup->server_version[0] != '\0')
|
||||
fprintf(out, "server-version = %s\n", backup->server_version);
|
||||
fio_printf(out, "server-version = %s\n", backup->server_version);
|
||||
|
||||
fprintf(out, "\n#Result backup info\n");
|
||||
fprintf(out, "timelineid = %d\n", backup->tli);
|
||||
fio_printf(out, "\n#Result backup info\n");
|
||||
fio_printf(out, "timelineid = %d\n", backup->tli);
|
||||
/* LSN returned by pg_start_backup */
|
||||
fprintf(out, "start-lsn = %X/%X\n",
|
||||
fio_printf(out, "start-lsn = %X/%X\n",
|
||||
(uint32) (backup->start_lsn >> 32),
|
||||
(uint32) backup->start_lsn);
|
||||
/* LSN returned by pg_stop_backup */
|
||||
fprintf(out, "stop-lsn = %X/%X\n",
|
||||
fio_printf(out, "stop-lsn = %X/%X\n",
|
||||
(uint32) (backup->stop_lsn >> 32),
|
||||
(uint32) backup->stop_lsn);
|
||||
|
||||
time2iso(timestamp, lengthof(timestamp), backup->start_time);
|
||||
fprintf(out, "start-time = '%s'\n", timestamp);
|
||||
fio_printf(out, "start-time = '%s'\n", timestamp);
|
||||
if (backup->end_time > 0)
|
||||
{
|
||||
time2iso(timestamp, lengthof(timestamp), backup->end_time);
|
||||
fprintf(out, "end-time = '%s'\n", timestamp);
|
||||
fio_printf(out, "end-time = '%s'\n", timestamp);
|
||||
}
|
||||
fprintf(out, "recovery-xid = " XID_FMT "\n", backup->recovery_xid);
|
||||
fio_printf(out, "recovery-xid = " XID_FMT "\n", backup->recovery_xid);
|
||||
if (backup->recovery_time > 0)
|
||||
{
|
||||
time2iso(timestamp, lengthof(timestamp), backup->recovery_time);
|
||||
fprintf(out, "recovery-time = '%s'\n", timestamp);
|
||||
fio_printf(out, "recovery-time = '%s'\n", timestamp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -480,20 +481,20 @@ pgBackupWriteControl(FILE *out, pgBackup *backup)
|
||||
* WAL segments in archive 'wal' directory.
|
||||
*/
|
||||
if (backup->data_bytes != BYTES_INVALID)
|
||||
fprintf(out, "data-bytes = " INT64_FORMAT "\n", backup->data_bytes);
|
||||
fio_printf(out, "data-bytes = " INT64_FORMAT "\n", backup->data_bytes);
|
||||
|
||||
if (backup->wal_bytes != BYTES_INVALID)
|
||||
fprintf(out, "wal-bytes = " INT64_FORMAT "\n", backup->wal_bytes);
|
||||
fio_printf(out, "wal-bytes = " INT64_FORMAT "\n", backup->wal_bytes);
|
||||
|
||||
fprintf(out, "status = %s\n", status2str(backup->status));
|
||||
fio_printf(out, "status = %s\n", status2str(backup->status));
|
||||
|
||||
/* 'parent_backup' is set if it is incremental backup */
|
||||
if (backup->parent_backup != 0)
|
||||
fprintf(out, "parent-backup-id = '%s'\n", base36enc(backup->parent_backup));
|
||||
fio_printf(out, "parent-backup-id = '%s'\n", base36enc(backup->parent_backup));
|
||||
|
||||
/* print connection info except password */
|
||||
if (backup->primary_conninfo)
|
||||
fprintf(out, "primary_conninfo = '%s'\n", backup->primary_conninfo);
|
||||
fio_printf(out, "primary_conninfo = '%s'\n", backup->primary_conninfo);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -506,14 +507,14 @@ write_backup(pgBackup *backup)
|
||||
char conf_path[MAXPGPATH];
|
||||
|
||||
pgBackupGetPath(backup, conf_path, lengthof(conf_path), BACKUP_CONTROL_FILE);
|
||||
fp = fopen(conf_path, "wt");
|
||||
fp = fio_open(conf_path, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (fp == NULL)
|
||||
elog(ERROR, "Cannot open configuration file \"%s\": %s", conf_path,
|
||||
strerror(errno));
|
||||
|
||||
pgBackupWriteControl(fp, backup);
|
||||
|
||||
fclose(fp);
|
||||
fio_close(fp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -527,16 +528,15 @@ pgBackupWriteFileList(pgBackup *backup, parray *files, const char *root)
|
||||
|
||||
pgBackupGetPath(backup, path, lengthof(path), DATABASE_FILE_LIST);
|
||||
|
||||
fp = fopen(path, "wt");
|
||||
fp = fio_open(path, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (fp == NULL)
|
||||
elog(ERROR, "cannot open file list \"%s\": %s", path,
|
||||
strerror(errno));
|
||||
|
||||
print_file_list(fp, files, root);
|
||||
|
||||
if (fflush(fp) != 0 ||
|
||||
fsync(fileno(fp)) != 0 ||
|
||||
fclose(fp))
|
||||
if (fio_flush(fp) != 0 ||
|
||||
fio_close(fp))
|
||||
elog(ERROR, "cannot write file list \"%s\": %s", path, strerror(errno));
|
||||
}
|
||||
|
||||
|
95
src/data.c
95
src/data.c
@ -13,7 +13,7 @@
|
||||
#include "storage/checksum.h"
|
||||
#include "storage/checksum_impl.h"
|
||||
#include <common/pg_lzcompress.h>
|
||||
|
||||
#include "utils/file.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
@ -419,12 +419,12 @@ compress_and_backup_page(pgFile *file, BlockNumber blknum,
|
||||
COMP_TRADITIONAL_CRC32(*crc, write_buffer, write_buffer_size);
|
||||
|
||||
/* write data page */
|
||||
if(fwrite(write_buffer, 1, write_buffer_size, out) != write_buffer_size)
|
||||
if (fio_write(out, write_buffer, write_buffer_size) != write_buffer_size)
|
||||
{
|
||||
int errno_tmp = errno;
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "File: %s, cannot write backup at block %u : %s",
|
||||
file->path, blknum, strerror(errno_tmp));
|
||||
}
|
||||
@ -512,7 +512,7 @@ backup_data_file(backup_files_arg* arguments,
|
||||
nblocks = file->size/BLCKSZ;
|
||||
|
||||
/* open backup file for write */
|
||||
out = fopen(to_path, PG_BINARY_W);
|
||||
out = fio_open(to_path, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (out == NULL)
|
||||
{
|
||||
int errno_tmp = errno;
|
||||
@ -571,18 +571,17 @@ backup_data_file(backup_files_arg* arguments,
|
||||
}
|
||||
|
||||
/* update file permission */
|
||||
if (chmod(to_path, FILE_PERMISSION) == -1)
|
||||
if (fio_chmod(to_path, FILE_PERMISSION, FIO_BACKUP_HOST) == -1)
|
||||
{
|
||||
int errno_tmp = errno;
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot change mode of \"%s\": %s", file->path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
|
||||
if (fflush(out) != 0 ||
|
||||
fsync(fileno(out)) != 0 ||
|
||||
fclose(out))
|
||||
if (fio_flush(out) != 0 ||
|
||||
fio_close(out))
|
||||
elog(ERROR, "cannot write backup file \"%s\": %s",
|
||||
to_path, strerror(errno));
|
||||
fclose(in);
|
||||
@ -639,9 +638,7 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
|
||||
* modified pages for differential restore. If the file does not exist,
|
||||
* re-open it with "w" to create an empty file.
|
||||
*/
|
||||
out = fopen(to_path, PG_BINARY_R "+");
|
||||
if (out == NULL && errno == ENOENT)
|
||||
out = fopen(to_path, PG_BINARY_W);
|
||||
out = fio_open(to_path, PG_BINARY_W "+", FIO_DB_HOST);
|
||||
if (out == NULL)
|
||||
{
|
||||
int errno_tmp = errno;
|
||||
@ -737,27 +734,27 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
|
||||
/*
|
||||
* Seek and write the restored page.
|
||||
*/
|
||||
if (fseek(out, write_pos, SEEK_SET) < 0)
|
||||
if (fio_seek(out, write_pos) < 0)
|
||||
elog(ERROR, "cannot seek block %u of \"%s\": %s",
|
||||
blknum, to_path, strerror(errno));
|
||||
|
||||
if (write_header)
|
||||
{
|
||||
if (fwrite(&header, 1, sizeof(header), out) != sizeof(header))
|
||||
if (fio_write(out, &header, sizeof(header)) != sizeof(header))
|
||||
elog(ERROR, "cannot write header of block %u of \"%s\": %s",
|
||||
blknum, file->path, strerror(errno));
|
||||
}
|
||||
|
||||
if (header.compressed_size < BLCKSZ)
|
||||
{
|
||||
if (fwrite(page.data, 1, BLCKSZ, out) != BLCKSZ)
|
||||
if (fio_write(out, page.data, BLCKSZ) != BLCKSZ)
|
||||
elog(ERROR, "cannot write block %u of \"%s\": %s",
|
||||
blknum, file->path, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if page wasn't compressed, we've read full block */
|
||||
if (fwrite(compressed_page.data, 1, BLCKSZ, out) != BLCKSZ)
|
||||
if (fio_write(out, compressed_page.data, BLCKSZ) != BLCKSZ)
|
||||
elog(ERROR, "cannot write block %u of \"%s\": %s",
|
||||
blknum, file->path, strerror(errno));
|
||||
}
|
||||
@ -775,7 +772,7 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
|
||||
size_t file_size = 0;
|
||||
|
||||
/* get file current size */
|
||||
fseek(out, 0, SEEK_END);
|
||||
fio_seek(out, 0);
|
||||
file_size = ftell(out);
|
||||
|
||||
if (file_size > file->n_blocks * BLCKSZ)
|
||||
@ -795,7 +792,7 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
|
||||
/*
|
||||
* Truncate file to this length.
|
||||
*/
|
||||
if (ftruncate(fileno(out), write_pos) != 0)
|
||||
if (fio_truncate(out, write_pos) != 0)
|
||||
elog(ERROR, "cannot truncate \"%s\": %s",
|
||||
file->path, strerror(errno));
|
||||
elog(VERBOSE, "Delta truncate file %s to block %u",
|
||||
@ -803,20 +800,19 @@ restore_data_file(const char *to_path, pgFile *file, bool allow_truncate,
|
||||
}
|
||||
|
||||
/* update file permission */
|
||||
if (chmod(to_path, file->mode) == -1)
|
||||
if (fio_chmod(to_path, file->mode, FIO_DB_HOST) == -1)
|
||||
{
|
||||
int errno_tmp = errno;
|
||||
|
||||
if (in)
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot change mode of \"%s\": %s", to_path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
|
||||
if (fflush(out) != 0 ||
|
||||
fsync(fileno(out)) != 0 ||
|
||||
fclose(out))
|
||||
if (fio_flush(out) != 0 ||
|
||||
fio_close(out))
|
||||
elog(ERROR, "cannot write \"%s\": %s", to_path, strerror(errno));
|
||||
if (in)
|
||||
fclose(in);
|
||||
@ -862,7 +858,7 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
|
||||
|
||||
/* open backup file for write */
|
||||
join_path_components(to_path, to_root, file->path + strlen(from_root) + 1);
|
||||
out = fopen(to_path, PG_BINARY_W);
|
||||
out = fio_open(to_path, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (out == NULL)
|
||||
{
|
||||
int errno_tmp = errno;
|
||||
@ -875,7 +871,7 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
|
||||
if (fstat(fileno(in), &st) == -1)
|
||||
{
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot stat \"%s\": %s", file->path,
|
||||
strerror(errno));
|
||||
}
|
||||
@ -888,12 +884,12 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
|
||||
if ((read_len = fread(buf, 1, sizeof(buf), in)) != sizeof(buf))
|
||||
break;
|
||||
|
||||
if (fwrite(buf, 1, read_len, out) != read_len)
|
||||
if (fio_write(out, buf, read_len) != read_len)
|
||||
{
|
||||
errno_tmp = errno;
|
||||
/* oops */
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot write to \"%s\": %s", to_path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
@ -907,7 +903,7 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
|
||||
if (!feof(in))
|
||||
{
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot read backup mode file \"%s\": %s",
|
||||
file->path, strerror(errno_tmp));
|
||||
}
|
||||
@ -915,12 +911,12 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
|
||||
/* copy odd part. */
|
||||
if (read_len > 0)
|
||||
{
|
||||
if (fwrite(buf, 1, read_len, out) != read_len)
|
||||
if (fio_write(out, buf, read_len) != read_len)
|
||||
{
|
||||
errno_tmp = errno;
|
||||
/* oops */
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot write to \"%s\": %s", to_path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
@ -936,18 +932,17 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
|
||||
file->crc = crc;
|
||||
|
||||
/* update file permission */
|
||||
if (chmod(to_path, st.st_mode) == -1)
|
||||
if (fio_chmod(to_path, st.st_mode, FIO_BACKUP_HOST) == -1)
|
||||
{
|
||||
errno_tmp = errno;
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
fio_close(out);
|
||||
elog(ERROR, "cannot change mode of \"%s\": %s", to_path,
|
||||
strerror(errno_tmp));
|
||||
}
|
||||
|
||||
if (fflush(out) != 0 ||
|
||||
fsync(fileno(out)) != 0 ||
|
||||
fclose(out))
|
||||
if (fio_flush(out) != 0 ||
|
||||
fio_close(out))
|
||||
elog(ERROR, "cannot write \"%s\": %s", to_path, strerror(errno));
|
||||
fclose(in);
|
||||
|
||||
@ -992,7 +987,7 @@ get_gz_error(gzFile gzf, int errnum)
|
||||
* Copy file attributes
|
||||
*/
|
||||
static void
|
||||
copy_meta(const char *from_path, const char *to_path, bool unlink_on_error)
|
||||
copy_meta(const char *from_path, const char *to_path, bool unlink_on_error, fio_location location)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
@ -1004,7 +999,7 @@ copy_meta(const char *from_path, const char *to_path, bool unlink_on_error)
|
||||
from_path, strerror(errno));
|
||||
}
|
||||
|
||||
if (chmod(to_path, st.st_mode) == -1)
|
||||
if (fio_chmod(to_path, st.st_mode, location) == -1)
|
||||
{
|
||||
if (unlink_on_error)
|
||||
unlink(to_path);
|
||||
@ -1064,7 +1059,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
|
||||
|
||||
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", to_path);
|
||||
|
||||
out = fopen(to_path_temp, PG_BINARY_W);
|
||||
out = fio_open(to_path_temp, PG_BINARY_W, FIO_BACKUP_HOST);
|
||||
if (out == NULL)
|
||||
elog(ERROR, "Cannot open destination WAL file \"%s\": %s",
|
||||
to_path_temp, strerror(errno));
|
||||
@ -1102,7 +1097,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (fwrite(buf, 1, read_len, out) != read_len)
|
||||
if (fio_write(out, buf, read_len) != read_len)
|
||||
{
|
||||
errno_temp = errno;
|
||||
unlink(to_path_temp);
|
||||
@ -1130,9 +1125,8 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (fflush(out) != 0 ||
|
||||
fsync(fileno(out)) != 0 ||
|
||||
fclose(out))
|
||||
if (fio_flush(out) != 0 ||
|
||||
fio_close(out))
|
||||
{
|
||||
errno_temp = errno;
|
||||
unlink(to_path_temp);
|
||||
@ -1150,9 +1144,9 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
|
||||
}
|
||||
|
||||
/* update file permission. */
|
||||
copy_meta(from_path, to_path_temp, true);
|
||||
copy_meta(from_path, to_path_temp, true, FIO_BACKUP_HOST);
|
||||
|
||||
if (rename(to_path_temp, to_path_p) < 0)
|
||||
if (fio_rename(to_path_temp, to_path_p, FIO_BACKUP_HOST) < 0)
|
||||
{
|
||||
errno_temp = errno;
|
||||
unlink(to_path_temp);
|
||||
@ -1223,7 +1217,7 @@ get_wal_file(const char *from_path, const char *to_path)
|
||||
/* open backup file for write */
|
||||
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", to_path);
|
||||
|
||||
out = fopen(to_path_temp, PG_BINARY_W);
|
||||
out = fio_open(to_path_temp, PG_BINARY_W, FIO_DB_HOST);
|
||||
if (out == NULL)
|
||||
elog(ERROR, "Cannot open destination WAL file \"%s\": %s",
|
||||
to_path_temp, strerror(errno));
|
||||
@ -1260,7 +1254,7 @@ get_wal_file(const char *from_path, const char *to_path)
|
||||
|
||||
if (read_len > 0)
|
||||
{
|
||||
if (fwrite(buf, 1, read_len, out) != read_len)
|
||||
if (fio_write(out, buf, read_len) != read_len)
|
||||
{
|
||||
errno_temp = errno;
|
||||
unlink(to_path_temp);
|
||||
@ -1284,9 +1278,8 @@ get_wal_file(const char *from_path, const char *to_path)
|
||||
}
|
||||
}
|
||||
|
||||
if (fflush(out) != 0 ||
|
||||
fsync(fileno(out)) != 0 ||
|
||||
fclose(out))
|
||||
if (fio_flush(out) != 0 ||
|
||||
fio_close(out))
|
||||
{
|
||||
errno_temp = errno;
|
||||
unlink(to_path_temp);
|
||||
@ -1318,9 +1311,9 @@ get_wal_file(const char *from_path, const char *to_path)
|
||||
}
|
||||
|
||||
/* update file permission. */
|
||||
copy_meta(from_path_p, to_path_temp, true);
|
||||
copy_meta(from_path_p, to_path_temp, true, FIO_DB_HOST);
|
||||
|
||||
if (rename(to_path_temp, to_path) < 0)
|
||||
if (fio_rename(to_path_temp, to_path, FIO_DB_HOST) < 0)
|
||||
{
|
||||
errno_temp = errno;
|
||||
unlink(to_path_temp);
|
||||
|
20
src/dir.c
20
src/dir.c
@ -9,6 +9,8 @@
|
||||
*/
|
||||
|
||||
#include "pg_probackup.h"
|
||||
#include "utils/file.h"
|
||||
|
||||
|
||||
#if PG_VERSION_NUM < 110000
|
||||
#include "catalog/catalog.h"
|
||||
@ -926,7 +928,7 @@ opt_tablespace_map(pgut_option *opt, const char *arg)
|
||||
*/
|
||||
void
|
||||
create_data_directories(const char *data_dir, const char *backup_dir,
|
||||
bool extract_tablespaces)
|
||||
bool extract_tablespaces, fio_location location)
|
||||
{
|
||||
parray *dirs,
|
||||
*links = NULL;
|
||||
@ -1026,11 +1028,11 @@ create_data_directories(const char *data_dir, const char *backup_dir,
|
||||
linked_path, relative_ptr);
|
||||
|
||||
/* Firstly, create linked directory */
|
||||
dir_create_dir(linked_path, DIR_PERMISSION);
|
||||
fio_mkdir(linked_path, DIR_PERMISSION, location);
|
||||
|
||||
join_path_components(to_path, data_dir, PG_TBLSPC_DIR);
|
||||
/* Create pg_tblspc directory just in case */
|
||||
dir_create_dir(to_path, DIR_PERMISSION);
|
||||
fio_mkdir(to_path, DIR_PERMISSION, location);
|
||||
|
||||
/* Secondly, create link */
|
||||
join_path_components(to_path, to_path, link_name);
|
||||
@ -1057,7 +1059,7 @@ create_directory:
|
||||
|
||||
/* This is not symlink, create directory */
|
||||
join_path_components(to_path, data_dir, relative_ptr);
|
||||
dir_create_dir(to_path, DIR_PERMISSION);
|
||||
fio_mkdir(to_path, DIR_PERMISSION, location);
|
||||
}
|
||||
|
||||
if (extract_tablespaces)
|
||||
@ -1204,7 +1206,7 @@ print_file_list(FILE *out, const parray *files, const char *root)
|
||||
if (root && strstr(path, root) == path)
|
||||
path = GetRelativePath(path, root);
|
||||
|
||||
fprintf(out, "{\"path\":\"%s\", \"size\":\"" INT64_FORMAT "\", "
|
||||
fio_printf(out, "{\"path\":\"%s\", \"size\":\"" INT64_FORMAT "\", "
|
||||
"\"mode\":\"%u\", \"is_datafile\":\"%u\", "
|
||||
"\"is_cfs\":\"%u\", \"crc\":\"%u\", "
|
||||
"\"compress_alg\":\"%s\"",
|
||||
@ -1213,19 +1215,19 @@ print_file_list(FILE *out, const parray *files, const char *root)
|
||||
deparse_compress_alg(file->compress_alg));
|
||||
|
||||
if (file->is_datafile)
|
||||
fprintf(out, ",\"segno\":\"%d\"", file->segno);
|
||||
fio_printf(out, ",\"segno\":\"%d\"", file->segno);
|
||||
|
||||
#ifndef WIN32
|
||||
if (S_ISLNK(file->mode))
|
||||
#else
|
||||
if (pgwin32_is_junction(file->path))
|
||||
#endif
|
||||
fprintf(out, ",\"linked\":\"%s\"", file->linked);
|
||||
fio_printf(out, ",\"linked\":\"%s\"", file->linked);
|
||||
|
||||
if (file->n_blocks != BLOCKNUM_INVALID)
|
||||
fprintf(out, ",\"n_blocks\":\"%i\"", file->n_blocks);
|
||||
fio_printf(out, ",\"n_blocks\":\"%i\"", file->n_blocks);
|
||||
|
||||
fprintf(out, "}\n");
|
||||
fio_printf(out, "}\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ do_add_instance(void)
|
||||
dir_create_dir(arclog_path, DIR_PERMISSION);
|
||||
|
||||
/*
|
||||
* Wite initial config. system-identifier and pgdata are set in
|
||||
* Write initial config. system-identifier and pgdata are set in
|
||||
* init subcommand and will never be updated.
|
||||
*/
|
||||
pgBackupConfigInit(config);
|
||||
|
@ -182,7 +182,7 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
|
||||
pgBackupGetPath(from_backup, from_database_path, lengthof(from_database_path),
|
||||
DATABASE_DIR);
|
||||
|
||||
create_data_directories(to_database_path, from_backup_path, false);
|
||||
create_data_directories(to_database_path, from_backup_path, false, FIO_BACKUP_HOST);
|
||||
|
||||
/*
|
||||
* Get list of files which will be modified or removed.
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "pg_getopt.h"
|
||||
#include "streamutil.h"
|
||||
#include "utils/file.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -65,7 +66,6 @@ char *replication_slot = NULL;
|
||||
/* backup options */
|
||||
bool backup_logs = false;
|
||||
bool smooth_checkpoint;
|
||||
bool is_remote_backup = false;
|
||||
/* Wait timeout for WAL segment archiving */
|
||||
uint32 archive_timeout = ARCHIVE_TIMEOUT_DEFAULT;
|
||||
const char *master_db = NULL;
|
||||
@ -73,6 +73,10 @@ const char *master_host = NULL;
|
||||
const char *master_port= NULL;
|
||||
const char *master_user = NULL;
|
||||
uint32 replica_timeout = REPLICA_TIMEOUT_DEFAULT;
|
||||
char *ssh_host;
|
||||
char *ssh_port;
|
||||
bool is_remote_agent;
|
||||
bool is_remote_backup;
|
||||
|
||||
/* restore options */
|
||||
static char *target_time;
|
||||
@ -165,17 +169,19 @@ static pgut_option options[] =
|
||||
{ 's', 16, "master-port", &master_port, SOURCE_CMDLINE, },
|
||||
{ 's', 17, "master-user", &master_user, SOURCE_CMDLINE, },
|
||||
{ 'u', 18, "replica-timeout", &replica_timeout, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S },
|
||||
/* TODO not completed feature. Make it unavailiable from user level
|
||||
{ 'b', 18, "remote", &is_remote_backup, SOURCE_CMDLINE, }, */
|
||||
{ 's', 19, "ssh-host", &ssh_host, SOURCE_CMDLINE, },
|
||||
{ 's', 20, "ssh-port", &ssh_port, SOURCE_CMDLINE, },
|
||||
{ 'b', 21, "agent", &is_remote_agent, SOURCE_CMDLINE, },
|
||||
{ 'b', 22, "remote", &is_remote_backup, SOURCE_CMDLINE, },
|
||||
/* restore options */
|
||||
{ 's', 20, "time", &target_time, SOURCE_CMDLINE },
|
||||
{ 's', 21, "xid", &target_xid, SOURCE_CMDLINE },
|
||||
{ 's', 22, "inclusive", &target_inclusive, SOURCE_CMDLINE },
|
||||
{ 'u', 23, "timeline", &target_tli, SOURCE_CMDLINE },
|
||||
{ 's', 30, "time", &target_time, SOURCE_CMDLINE },
|
||||
{ 's', 31, "xid", &target_xid, SOURCE_CMDLINE },
|
||||
{ 's', 32, "inclusive", &target_inclusive, SOURCE_CMDLINE },
|
||||
{ 'u', 33, "timeline", &target_tli, SOURCE_CMDLINE },
|
||||
{ 'f', 'T', "tablespace-mapping", opt_tablespace_map, SOURCE_CMDLINE },
|
||||
{ 'b', 24, "immediate", &target_immediate, SOURCE_CMDLINE },
|
||||
{ 's', 25, "recovery-target-name", &target_name, SOURCE_CMDLINE },
|
||||
{ 's', 26, "recovery-target-action", &target_action, SOURCE_CMDLINE },
|
||||
{ 'b', 34, "immediate", &target_immediate, SOURCE_CMDLINE },
|
||||
{ 's', 35, "recovery-target-name", &target_name, SOURCE_CMDLINE },
|
||||
{ 's', 36, "recovery-target-action", &target_action, SOURCE_CMDLINE },
|
||||
{ 'b', 'R', "restore-as-replica", &restore_as_replica, SOURCE_CMDLINE },
|
||||
{ 'b', 27, "no-validate", &restore_no_validate, SOURCE_CMDLINE },
|
||||
{ 's', 28, "lsn", &target_lsn, SOURCE_CMDLINE },
|
||||
@ -372,10 +378,28 @@ main(int argc, char *argv[])
|
||||
if (!is_absolute_path(backup_path))
|
||||
elog(ERROR, "-B, --backup-path must be an absolute path");
|
||||
|
||||
/* Ensure that backup_path is a path to a directory */
|
||||
rc = stat(backup_path, &stat_buf);
|
||||
if (rc != -1 && !S_ISDIR(stat_buf.st_mode))
|
||||
elog(ERROR, "-B, --backup-path must be a path to directory");
|
||||
if (ssh_host != NULL &&
|
||||
(backup_subcmd == BACKUP_CMD || backup_subcmd == ADD_INSTANCE_CMD || backup_subcmd == RESTORE_CMD))
|
||||
{
|
||||
if (is_remote_agent) {
|
||||
if (backup_subcmd != BACKUP_CMD) {
|
||||
fio_communicate(STDIN_FILENO, STDOUT_FILENO);
|
||||
return 0;
|
||||
}
|
||||
fio_redirect(STDIN_FILENO, STDOUT_FILENO);
|
||||
} else {
|
||||
/* Execute remote probackup */
|
||||
remote_execute(argc, argv, backup_subcmd == BACKUP_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_remote_agent)
|
||||
{
|
||||
/* Ensure that backup_path is a path to a directory */
|
||||
rc = stat(backup_path, &stat_buf);
|
||||
if (rc != -1 && !S_ISDIR(stat_buf.st_mode))
|
||||
elog(ERROR, "-B, --backup-path must be a path to directory");
|
||||
}
|
||||
|
||||
/* command was initialized for a few commands */
|
||||
if (command)
|
||||
@ -409,7 +433,7 @@ main(int argc, char *argv[])
|
||||
* for all commands except init, which doesn't take this parameter
|
||||
* and add-instance which creates new instance.
|
||||
*/
|
||||
if (backup_subcmd != INIT_CMD && backup_subcmd != ADD_INSTANCE_CMD)
|
||||
if (backup_subcmd != INIT_CMD && backup_subcmd != ADD_INSTANCE_CMD && !is_remote_agent)
|
||||
{
|
||||
if (access(backup_instance_path, F_OK) != 0)
|
||||
elog(ERROR, "Instance '%s' does not exist in this backup catalog",
|
||||
@ -523,7 +547,7 @@ main(int argc, char *argv[])
|
||||
|
||||
elog(INFO, "Backup start, pg_probackup version: %s, backup ID: %s, backup mode: %s, instance: %s, stream: %s, remote: %s",
|
||||
PROGRAM_VERSION, base36enc(start_time), backup_mode, instance_name,
|
||||
stream_wal ? "true" : "false", is_remote_backup ? "true" : "false");
|
||||
stream_wal ? "true" : "false", ssh_host ? "true" : "false");
|
||||
|
||||
return do_backup(start_time);
|
||||
}
|
||||
|
@ -10,23 +10,23 @@
|
||||
#ifndef PG_PROBACKUP_H
|
||||
#define PG_PROBACKUP_H
|
||||
|
||||
#include "postgres_fe.h"
|
||||
#include "libpq-fe.h"
|
||||
|
||||
#include "access/xlog_internal.h"
|
||||
#include "utils/pg_crc.h"
|
||||
#include <postgres_fe.h>
|
||||
#include <libpq-fe.h>
|
||||
#include <access/xlog_internal.h>
|
||||
#include <utils/pg_crc.h>
|
||||
|
||||
#ifdef FRONTEND
|
||||
#undef FRONTEND
|
||||
#include "port/atomics.h"
|
||||
#include <port/atomics.h>
|
||||
#define FRONTEND
|
||||
#else
|
||||
#include "port/atomics.h"
|
||||
#include <port/atomics.h>
|
||||
#endif
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "utils/parray.h"
|
||||
#include "utils/pgut.h"
|
||||
#include "utils/file.h"
|
||||
|
||||
#include "datapagemap.h"
|
||||
|
||||
@ -325,11 +325,14 @@ extern char *replication_slot;
|
||||
extern bool smooth_checkpoint;
|
||||
#define ARCHIVE_TIMEOUT_DEFAULT 300
|
||||
extern uint32 archive_timeout;
|
||||
extern bool is_remote_backup;
|
||||
extern char *ssh_port;
|
||||
extern char *ssh_host;
|
||||
extern const char *master_db;
|
||||
extern const char *master_host;
|
||||
extern const char *master_port;
|
||||
extern const char *master_user;
|
||||
extern bool is_remote_backup;
|
||||
extern bool is_remote_agent;
|
||||
#define REPLICA_TIMEOUT_DEFAULT 300
|
||||
extern uint32 replica_timeout;
|
||||
|
||||
@ -472,6 +475,7 @@ extern pgBackup* find_parent_full_backup(pgBackup *current_backup);
|
||||
extern int scan_parent_chain(pgBackup *current_backup, pgBackup **result_backup);
|
||||
extern bool is_parent(time_t parent_backup_time, pgBackup *child_backup, bool inclusive);
|
||||
extern int get_backup_index_number(parray *backup_list, pgBackup *backup);
|
||||
extern void remote_execute(int argc, char *argv[], bool do_backup);
|
||||
|
||||
#define COMPRESS_ALG_DEFAULT NOT_DEFINED_COMPRESS
|
||||
#define COMPRESS_LEVEL_DEFAULT 1
|
||||
@ -484,7 +488,8 @@ extern void dir_list_file(parray *files, const char *root, bool exclude,
|
||||
bool omit_symlink, bool add_root);
|
||||
extern void create_data_directories(const char *data_dir,
|
||||
const char *backup_dir,
|
||||
bool extract_tablespaces);
|
||||
bool extract_tablespaces,
|
||||
fio_location location);
|
||||
|
||||
extern void read_tablespace_map(parray *files, const char *backup_dir);
|
||||
extern void opt_tablespace_map(pgut_option *opt, const char *arg);
|
||||
|
@ -445,7 +445,7 @@ restore_backup(pgBackup *backup)
|
||||
* this_backup_path = $BACKUP_PATH/backups/instance_name/backup_id
|
||||
*/
|
||||
pgBackupGetPath(backup, this_backup_path, lengthof(this_backup_path), NULL);
|
||||
create_data_directories(pgdata, this_backup_path, true);
|
||||
create_data_directories(pgdata, this_backup_path, true, FIO_DB_HOST);
|
||||
|
||||
/*
|
||||
* Get list of files which need to be restored.
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "pgut.h"
|
||||
#include "logger.h"
|
||||
#include "file.h"
|
||||
|
||||
#define MAX_TZDISP_HOUR 15 /* maximum allowed hour part */
|
||||
#define SECS_PER_MINUTE 60
|
||||
@ -1147,7 +1148,7 @@ pgut_readopt(const char *path, pgut_option options[], int elevel, bool strict)
|
||||
if (!options)
|
||||
return parsed_options;
|
||||
|
||||
if ((fp = pgut_fopen(path, "rt", true)) == NULL)
|
||||
if ((fp = fio_open_stream(path, FIO_BACKUP_HOST)) == NULL)
|
||||
return parsed_options;
|
||||
|
||||
while (fgets(buf, lengthof(buf), fp))
|
||||
@ -1181,7 +1182,7 @@ pgut_readopt(const char *path, pgut_option options[], int elevel, bool strict)
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fio_close_stream(fp);
|
||||
|
||||
return parsed_options;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user