From 1d9a3e47733a0e1f48e697ff97dd262fe2e58b91 Mon Sep 17 00:00:00 2001 From: liuzhanfeng2 Date: Mon, 20 Nov 2023 17:06:34 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B5=84=E6=BA=90=E6=B1=A0=E5=8C=96=E9=80=82?= =?UTF-8?q?=E9=85=8Dgs=5Fprobackup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/pg_probackup/backup.cpp | 142 +++++++++------ src/bin/pg_probackup/data.cpp | 34 +++- src/bin/pg_probackup/dir.cpp | 34 ++-- src/bin/pg_probackup/merge.cpp | 66 +++++-- src/bin/pg_probackup/parsexlog.cpp | 16 +- src/bin/pg_probackup/pg_probackupb.h | 4 +- src/bin/pg_probackup/pg_probackupc.h | 4 +- src/bin/pg_probackup/ptrack.cpp | 26 ++- src/bin/pg_probackup/restore.cpp | 161 +++++++++++++----- src/bin/pg_probackup/show.cpp | 6 + src/bin/pg_probackup/util.cpp | 7 +- .../storage/access/transam/cbmparsexlog.cpp | 18 +- src/include/port.h | 2 + 13 files changed, 375 insertions(+), 145 deletions(-) diff --git a/src/bin/pg_probackup/backup.cpp b/src/bin/pg_probackup/backup.cpp index 4286498d4..d3bcb2ce7 100644 --- a/src/bin/pg_probackup/backup.cpp +++ b/src/bin/pg_probackup/backup.cpp @@ -263,7 +263,7 @@ static void run_backup_threads(char *external_prefix, char *database_path, char pfree(threads_args); } -static void start_stream_wal(const char *database_path, PGconn *backup_conn) +static void start_stream_wal(const char *database_path, const char *dssdata_path, PGconn *backup_conn) { static char dst_backup_path[MAXPGPATH]; @@ -271,7 +271,15 @@ static void start_stream_wal(const char *database_path, PGconn *backup_conn) stream_stop_timeout = checkpoint_timeout(backup_conn); stream_stop_timeout = stream_stop_timeout + stream_stop_timeout * 0.1; - join_path_components(dst_backup_path, database_path, PG_XLOG_DIR); + if (IsDssMode()) { + error_t rc; + rc = snprintf_s(dst_backup_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s%d", dssdata_path, + PG_XLOG_DIR, instance_config.dss.instance_id); + securec_check_ss_c(rc, "\0", "\0"); + } else { + join_path_components(dst_backup_path, database_path, PG_XLOG_DIR); + } + fio_mkdir(dst_backup_path, DIR_PERMISSION, FIO_BACKUP_HOST); stream_thread_arg.basedir = dst_backup_path; @@ -390,16 +398,13 @@ static void get_prev_backup_info(parray **backup_list, pgBackup **prev_back, par *prev_back = prev_backup; } -static void calc_pgdata_bytes() +static void calc_data_bytes() { int i; - char pretty_bytes[20]; + char pretty_dssdata_bytes[20]; + char pretty_pgdata_bytes[20]; - if (parray_num(backup_files_list) < 100) - elog(ERROR, "PGDATA is almost empty. Either it was concurrently deleted or " - "gs_probackup do not possess sufficient permissions to list PGDATA content"); - - /* Calculate pgdata_bytes */ + /* Calculate pgdata_bytes and dssdata_bytes */ for (i = 0; i < (int)parray_num(backup_files_list); i++) { pgFile *file = (pgFile *) parray_get(backup_files_list, i); @@ -407,17 +412,25 @@ static void calc_pgdata_bytes() if (file->external_dir_num != 0) continue; - if (S_ISDIR(file->mode)) - { - current.pgdata_bytes += 4096; - continue; + if (S_ISDIR(file->mode)) { + if (is_dss_type(file->type)) + current.dssdata_bytes += 4096; + else + current.pgdata_bytes += 4096; + } else { + if (is_dss_type(file->type)) + current.dssdata_bytes += file->size; + else + current.pgdata_bytes += file->size; } - - current.pgdata_bytes += file->size; } - pretty_size(current.pgdata_bytes, pretty_bytes, lengthof(pretty_bytes)); - elog(INFO, "PGDATA size: %s", pretty_bytes); + pretty_size(current.pgdata_bytes, pretty_pgdata_bytes, lengthof(pretty_pgdata_bytes)); + elog(INFO, "PGDATA size: %s", pretty_pgdata_bytes); + if (IsDssMode()) { + pretty_size(current.dssdata_bytes, pretty_dssdata_bytes, lengthof(pretty_dssdata_bytes)); + elog(INFO, "DSSDATA size: %s", pretty_dssdata_bytes); + } } static void add_xlog_files_into_backup_list(const char *database_path, const char *dssdata_path, @@ -432,28 +445,11 @@ static void add_xlog_files_into_backup_list(const char *database_path, const cha /* Scan backup PG_XLOG_DIR */ xlog_files_list = parray_new(); - /* link dssdata's pg_xlog to database's pg_xlog */ - if (enable_dss) { - char database_xlog[MAXPGPATH]; - char dssdata_xlog[MAXPGPATH]; + if (IsDssMode()) { errno_t rc; - rc = snprintf_s(dssdata_xlog, MAXPGPATH, MAXPGPATH - 1, "%s/%s%d", dssdata_path, PG_XLOG_DIR, instance_id); + rc = snprintf_s(pg_xlog_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s%d", dssdata_path, PG_XLOG_DIR, instance_id); securec_check_ss_c(rc, "\0", "\0"); - join_path_components(database_xlog, database_path, PG_XLOG_DIR); - - /* dssdata_xlog is already exist, destory it and recreate */ - if (rmdir(dssdata_xlog) != 0) { - elog(ERROR, "can not remove xlog dir \"%s\" : %s", dssdata_xlog, strerror(errno)); - } - - if (symlink(database_xlog, dssdata_xlog) < 0) { - elog(ERROR, "can not link dss xlog dir \"%s\" to database xlog dir \"%s\": %s", dssdata_xlog, database_xlog, - strerror(errno)); - } - - rc = strcpy_s(pg_xlog_path, MAXPGPATH, dssdata_xlog); - securec_check_c(rc, "\0", "\0"); parent_path = dssdata_path; } else { join_path_components(pg_xlog_path, database_path, PG_XLOG_DIR); @@ -683,7 +679,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool /* start stream replication */ if (stream_wal) { - start_stream_wal(database_path, backup_conn); + start_stream_wal(database_path, dssdata_path, backup_conn); } /* initialize backup list */ @@ -736,11 +732,17 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool */ if (parray_num(backup_files_list) < 100) - elog(ERROR, "PGDATA is almost empty. Either it was concurrently deleted or " - "gs_probackup do not possess sufficient permissions to list PGDATA content"); + { + if (IsDssMode()) + elog(ERROR, "VGNAME is almost empty. Either it was concurrently deleted or " + "gs_probackup do not possess sufficient permissions to list VGNAME content"); + else + elog(ERROR, "PGDATA is almost empty. Either it was concurrently deleted or " + "gs_probackup do not possess sufficient permissions to list PGDATA content"); + } - /* Calculate pgdata_bytes */ - calc_pgdata_bytes(); + /* Calculate pgdata_bytes and dssdata_bytes */ + calc_data_bytes(); /* * Sort pathname ascending. It is necessary to create intermediate * directories sequentially. @@ -943,9 +945,6 @@ do_backup(time_t start_time, pgSetBackupParams *set_backup_params, elog(ERROR, "required parameter not specified: PGDATA " "(-D, --pgdata)"); - if (IsDssMode() && current.backup_mode != BACKUP_MODE_FULL) - elog(ERROR, "only support full backup when enable dss."); - /* Update backup status and other metainfo. */ current.status = BACKUP_STATUS_RUNNING; current.start_time = start_time; @@ -1434,8 +1433,22 @@ wait_wal_lsn(XLogRecPtr target_lsn, bool is_start_lsn, TimeLineID tli, */ if (in_stream_dir) { - pgBackupGetPath2(¤t, pg_wal_dir, lengthof(pg_wal_dir), - DATABASE_DIR, PG_XLOG_DIR); + if (IsDssMode()) + { + errno_t rc; + char dss_xlog[MAXPGPATH]; + + rc = snprintf_s(dss_xlog, MAXPGPATH, MAXPGPATH - 1, "%s%d", + PG_XLOG_DIR, instance_config.dss.instance_id); + securec_check_ss_c(rc, "\0", "\0"); + pgBackupGetPath2(¤t, pg_wal_dir, lengthof(pg_wal_dir), + DSSDATA_DIR, dss_xlog); + } + else + { + pgBackupGetPath2(¤t, pg_wal_dir, lengthof(pg_wal_dir), + DATABASE_DIR, PG_XLOG_DIR); + } join_path_components(wal_segment_path, pg_wal_dir, wal_segment); wal_segment_dir = pg_wal_dir; } @@ -1558,9 +1571,21 @@ static void get_valid_stop_lsn(pgBackup *backup, bool *stop_lsn_exists, XLogRecP if (stream_wal) { - pgBackupGetPath2(backup, stream_xlog_path, - lengthof(stream_xlog_path), + if (IsDssMode()) + { + errno_t rc; + char dss_xlog[MAXPGPATH]; + rc = snprintf_s(dss_xlog, MAXPGPATH, MAXPGPATH - 1, "%s%d", PG_XLOG_DIR, + instance_config.dss.instance_id); + securec_check_ss_c(rc, "\0", "\0"); + pgBackupGetPath2(backup, stream_xlog_path, lengthof(stream_xlog_path), + DSSDATA_DIR, dss_xlog); + } + else + { + pgBackupGetPath2(backup, stream_xlog_path, lengthof(stream_xlog_path), DATABASE_DIR, PG_XLOG_DIR); + } xlog_path = stream_xlog_path; } else @@ -1961,7 +1986,7 @@ pg_stop_backup(pgBackup *backup, PGconn *pg_startbackup_conn, if (backup != NULL) { char *xlog_path, - stream_xlog_path[MAXPGPATH]; + stream_xlog_path[MAXPGPATH]; /* * Wait for stop_lsn to be archived or streamed. @@ -1983,9 +2008,22 @@ pg_stop_backup(pgBackup *backup, PGconn *pg_startbackup_conn, if (stream_thread_arg.ret == 1) elog(ERROR, "WAL streaming failed"); - pgBackupGetPath2(backup, stream_xlog_path, - lengthof(stream_xlog_path), - DATABASE_DIR, PG_XLOG_DIR); + if (IsDssMode()) + { + errno_t rc; + char dss_xlog[MAXPGPATH]; + + rc = snprintf_s(dss_xlog, MAXPGPATH, MAXPGPATH - 1, "%s%d", + PG_XLOG_DIR, instance_config.dss.instance_id); + securec_check_ss_c(rc, "\0", "\0"); + pgBackupGetPath2(backup, stream_xlog_path, lengthof(stream_xlog_path), + DSSDATA_DIR, dss_xlog); + } + else + { + pgBackupGetPath2(backup, stream_xlog_path, lengthof(stream_xlog_path), + DATABASE_DIR, PG_XLOG_DIR); + } xlog_path = stream_xlog_path; } else diff --git a/src/bin/pg_probackup/data.cpp b/src/bin/pg_probackup/data.cpp index 523b45a73..dbf3a251f 100644 --- a/src/bin/pg_probackup/data.cpp +++ b/src/bin/pg_probackup/data.cpp @@ -498,7 +498,7 @@ prepare_page(ConnectionArgs *conn_arg, /* read the block */ int offset = blknum * BLCKSZ; int fileStartOff = offset - (offset % DSS_BLCKSZ); - if (IsDssMode() && file->size - fileStartOff >= DSS_BLCKSZ) + if (current.backup_mode == BACKUP_MODE_FULL && IsDssMode() && file->size - fileStartOff >= DSS_BLCKSZ) { int preReadOff = offset % DSS_BLCKSZ; if (offset / DSS_BLCKSZ == preReadBuf->num) @@ -570,7 +570,7 @@ prepare_page(ConnectionArgs *conn_arg, blknum, from_fullpath, read_len, BLCKSZ); } else - { + { /* We have BLCKSZ of raw data, validate it */ rc = validate_one_page(page, absolute_blknum, InvalidXLogRecPtr, page_st, @@ -739,7 +739,7 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file, * NOTE This is a normal situation, if the file size has changed * since the moment we computed it. */ - file->n_blocks = file->size/BLCKSZ; + file->n_blocks = file->size / BLCKSZ; /* * Skip unchanged file only if it exists in previous backup. @@ -1305,7 +1305,7 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers /* If page is compressed and restore is in remote mode, send compressed * page to the remote side. */ - if (IsDssMode() && targetSize >= DSS_BLCKSZ) + if (!map && IsDssMode() && targetSize >= DSS_BLCKSZ) { if (is_compressed) { @@ -1601,11 +1601,31 @@ backup_non_data_file_internal(const char *from_fullpath, fio_location from_locat /* open backup file for write */ out = fopen(to_fullpath, PG_BINARY_W); if (out == NULL) - elog(ERROR, "Cannot open destination file \"%s\": %s", - to_fullpath, strerror(errno)); + { + if (file->external_dir_num) + { + char parent[MAXPGPATH]; + errno_t rc = 0; + + rc = strncpy_s(parent, MAXPGPATH, to_fullpath, MAXPGPATH - 1); + securec_check_c(rc, "", ""); + get_parent_directory(parent); + + dir_create_dir(parent, DIR_PERMISSION); + out = fopen(to_fullpath, PG_BINARY_W); + if (out == NULL) + elog(ERROR, "Cannot open destination file \"%s\": %s", + to_fullpath, strerror(errno)); + } + else + { + elog(ERROR, "Cannot open destination file \"%s\": %s", + to_fullpath, strerror(errno)); + } + } /* update file permission */ - if (!is_dss_file(from_fullpath)) + if (!is_dss_type(file->type)) { if (chmod(to_fullpath, file->mode) == -1) elog(ERROR, "Cannot change mode of \"%s\": %s", to_fullpath, diff --git a/src/bin/pg_probackup/dir.cpp b/src/bin/pg_probackup/dir.cpp index 44b17ecb2..b2f21264d 100644 --- a/src/bin/pg_probackup/dir.cpp +++ b/src/bin/pg_probackup/dir.cpp @@ -450,9 +450,9 @@ pgFileCompareRelPathWithExternal(const void *f1, const void *f2) res = strcmp(f1p->rel_path, f2p->rel_path); if (res == 0) { - if (f1p->external_dir_num > f2p->external_dir_num) + if (f1p->external_dir_num > f2p->external_dir_num || f1p->type > f2p->type) return 1; - else if (f1p->external_dir_num < f2p->external_dir_num) + else if (f1p->external_dir_num < f2p->external_dir_num || f1p->type < f2p->type) return -1; else return 0; @@ -691,16 +691,21 @@ dir_check_file(pgFile *file, bool backup_logs, bool backup_replslots) Oid tblspcOid; char tmp_rel_path[MAXPGPATH]; + if (in_tablespace && IsDssMode()) + return CHECK_FALSE; /* * Valid path for the tablespace is * pg_tblspc/tblsOid/TABLESPACE_VERSION_DIRECTORY */ - if (!path_is_prefix_of_path(PG_TBLSPC_DIR, file->rel_path)) - return CHECK_FALSE; - sscanf_res = sscanf_s(file->rel_path, PG_TBLSPC_DIR "/%u/%s", + if (!IsDssMode()) + { + if (!in_tablespace) + return CHECK_FALSE; + sscanf_res = sscanf_s(file->rel_path, PG_TBLSPC_DIR "/%u/%s", &tblspcOid, tmp_rel_path, MAXPGPATH); - if (sscanf_res == 0) - return CHECK_FALSE; + if (sscanf_res == 0) + return CHECK_FALSE; + } } /* skip other instance files in dss mode */ @@ -760,7 +765,7 @@ static char check_in_dss(pgFile *file, int include_id) static char check_in_tablespace(pgFile *file, bool in_tablespace) { -if (in_tablespace) + if (in_tablespace) { int sscanf_res; char tmp_rel_path[MAXPGPATH]; @@ -1235,7 +1240,7 @@ opt_externaldir_map(ConfigOption *opt, const char *arg) */ void create_data_directories(parray *dest_files, const char *data_dir, const char *backup_dir, - bool extract_tablespaces, bool incremental, fio_location location) + bool extract_tablespaces, bool incremental, fio_location location, bool is_restore) { size_t i = 0; parray *links = NULL; @@ -1312,7 +1317,7 @@ create_data_directories(parray *dest_files, const char *data_dir, const char *ba if (dir->external_dir_num != 0) continue; - if (is_dss_type(dir->type)) { + if (is_dss_type(dir->type) && is_restore) { if (is_ss_xlog(dir->rel_path)) { ss_createdir(dir->rel_path, instance_config.dss.vgdata, instance_config.dss.vglog); continue; @@ -1348,7 +1353,7 @@ create_data_directories(parray *dest_files, const char *data_dir, const char *ba { const char *linked_path = get_tablespace_mapping((*link)->linked); - if (!is_absolute_path(linked_path)) + if (!is_absolute_path(linked_path) && !ss_is_absolute_path(linked_path)) elog(ERROR, "Tablespace directory is not an absolute path: %s\n", linked_path); @@ -1499,7 +1504,7 @@ check_tablespace_mapping(pgBackup *backup, bool incremental, bool *tblspaces_are break; } - if (!is_absolute_path(linked_path)) + if (!is_absolute_path(linked_path) && !ss_is_absolute_path(linked_path)) elog(ERROR, "tablespace directory is not an absolute path: %s\n", linked_path); @@ -1551,6 +1556,9 @@ check_external_dir_mapping(pgBackup *backup, bool incremental) if (strcmp(cell->old_dir, external_dir) == 0) { + if (is_dss_file(cell->new_dir)) + elog(ERROR, "New external directory path \"%s\" " + "contains dss path, which is not allow.", cell->new_dir); /* Swap new dir name with old one, it is used by 2-nd step */ parray_set(external_dirs_to_restore, i, pgut_strdup(cell->new_dir)); @@ -1966,7 +1974,7 @@ make_external_directory_list(const char *colon_separated_dirs, bool remap) char *external_path = pg_strdup(p); canonicalize_path(external_path); - if (is_absolute_path(external_path)) + if (is_absolute_path(external_path) || ss_is_absolute_path(external_path)) { if (remap) { diff --git a/src/bin/pg_probackup/merge.cpp b/src/bin/pg_probackup/merge.cpp index d60b59d6e..17088e66d 100644 --- a/src/bin/pg_probackup/merge.cpp +++ b/src/bin/pg_probackup/merge.cpp @@ -27,6 +27,7 @@ typedef struct const char *full_database_dir; const char *full_external_prefix; + const char *full_dss_dir; // size_t in_place_merge_bytes; bool compression_match; @@ -55,15 +56,15 @@ get_external_index(const char *key, const parray *list); static void merge_data_file(parray *parent_chain, pgBackup *full_backup, - pgBackup *dest_backup, pgFile *dest_file, - pgFile *tmp_file, const char *to_root, bool use_bitmap, - bool is_retry); + pgBackup *dest_backup, pgFile *dest_file, + pgFile *tmp_file, const char *full_database_dir, const char *full_dss_dir, + bool use_bitmap, bool is_retry); static void merge_non_data_file(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup, pgFile *dest_file, pgFile *tmp_file, const char *full_database_dir, - const char *full_external_prefix); + const char *full_dss_dir, const char *full_external_prefix); static pgBackup* find_dest_backup(parray *backups, time_t backup_id); static pgBackup *check_dest_backup(parray *backups, pgBackup *full_backup); @@ -74,6 +75,7 @@ static void get_backup_files(pgBackup *dest_backup, pgBackup *full_backup, char *full_external_prefix, char *full_database_dir, + char *full_dss_dir, parray *dest_externals, parray *full_externals, parray *parent_chain); @@ -81,6 +83,7 @@ static void threads_handle(pgBackup *dest_backup, pgBackup *full_backup, char *full_external_prefix, char *full_database_dir, + char *full_dss_dir, pthread_t *threads, merge_files_arg *threads_args, parray *parent_chain, @@ -91,6 +94,7 @@ static void threads_handle(pgBackup *dest_backup, static void del_full_backup_files(pgBackup *dest_backup, pgBackup *full_backup, const char *full_database_dir, + const char *full_dss_dir, parray *full_externals); static void merge_rename(pgBackup *dest_backup, pgBackup *full_backup, @@ -106,7 +110,7 @@ static void forward_compatibility_check(parray *parent_chain); * Implementation of MERGE command. * * - Find target and its parent full backup - * - Merge data files of target, parent and and intermediate backups + * - Merge data files of target, parent and intermediate backups * - Remove unnecessary files, which doesn't exist in the target backup anymore */ void @@ -513,6 +517,7 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup) int i; char full_external_prefix[MAXPGPATH]; char full_database_dir[MAXPGPATH]; + char full_dss_dir[MAXPGPATH]; parray *full_externals = NULL, *dest_externals = NULL; @@ -616,13 +621,13 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup) validate_parent_chain(parent_chain, dest_backup); get_backup_files(dest_backup, full_backup, full_external_prefix, full_database_dir, - dest_externals, full_externals, parent_chain); + full_dss_dir, dest_externals, full_externals, parent_chain); threads_handle(dest_backup, full_backup, full_external_prefix, full_database_dir, - threads, threads_args, parent_chain, compression_match, + full_dss_dir, threads, threads_args, parent_chain, compression_match, program_version_match, is_retry, result_filelist); - del_full_backup_files(dest_backup, full_backup, full_database_dir, full_externals); + del_full_backup_files(dest_backup, full_backup, full_database_dir, full_dss_dir, full_externals); merge_delete: for (i = parray_num(parent_chain) - 2; i >= 0; i--) @@ -697,6 +702,7 @@ static void get_backup_files(pgBackup *dest_backup, pgBackup *full_backup, char *full_external_prefix, char *full_database_dir, + char *full_dss_dir, parray *dest_externals, parray *full_externals, parray *parent_chain) @@ -728,12 +734,17 @@ static void get_backup_files(pgBackup *dest_backup, /* Construct path to database dir: /backup_dir/instance_name/FULL/database */ join_path_components(full_database_dir, full_backup->root_dir, DATABASE_DIR); + /* Construct path to vgname dir: /backup_dir/instance_name/FULL/dssdata */ + join_path_components(full_dss_dir, full_backup->root_dir, DSSDATA_DIR); /* Construct path to external dir: /backup_dir/instance_name/FULL/external */ join_path_components(full_external_prefix, full_backup->root_dir, EXTERNAL_DIR); - /* Create directories */ + /* Create directories in database_dir*/ create_data_directories(dest_backup->files, full_database_dir, - dest_backup->root_dir, false, false, FIO_BACKUP_HOST); + dest_backup->root_dir, false, false, FIO_BACKUP_HOST, false); + /* Create directories in dssdata_dir */ + create_data_directories(dest_backup->files, full_dss_dir, + dest_backup->root_dir, false, false, FIO_BACKUP_HOST, false); /* External directories stuff */ if (dest_backup->external_dir_str) @@ -752,6 +763,7 @@ static void threads_handle(pgBackup *dest_backup, pgBackup *full_backup, char *full_external_prefix, char *full_database_dir, + char *full_dss_dir, pthread_t *threads, merge_files_arg *threads_args, parray *parent_chain, @@ -806,6 +818,7 @@ static void threads_handle(pgBackup *dest_backup, arg->dest_backup = dest_backup; arg->full_backup = full_backup; arg->full_database_dir = full_database_dir; + arg->full_dss_dir = full_dss_dir; arg->full_external_prefix = full_external_prefix; arg->compression_match = compression_match; @@ -926,6 +939,7 @@ static void threads_handle(pgBackup *dest_backup, static void del_full_backup_files(pgBackup *dest_backup, pgBackup *full_backup, const char *full_database_dir, + const char *full_dss_dir, parray *full_externals) { /* Delete FULL backup files, that do not exists in destination backup @@ -950,7 +964,10 @@ static void del_full_backup_files(pgBackup *dest_backup, char full_file_path[MAXPGPATH]; /* We need full path, file object has relative path */ - join_path_components(full_file_path, full_database_dir, full_file->rel_path); + if (is_dss_type(full_file->type)) + join_path_components(full_file_path, full_dss_dir, full_file->rel_path); + else + join_path_components(full_file_path, full_database_dir, full_file->rel_path); pgFileDelete(full_file->mode, full_file_path); elog(VERBOSE, "Deleted \"%s\"", full_file_path); @@ -1094,6 +1111,7 @@ merge_files(void *arg) tmp_file->is_cfs = dest_file->is_cfs; tmp_file->external_dir_num = dest_file->external_dir_num; tmp_file->dbOid = dest_file->dbOid; + tmp_file->type = dest_file->type; /* Directories were created before */ if (S_ISDIR(dest_file->mode)) @@ -1127,6 +1145,7 @@ merge_files(void *arg) arguments->dest_backup, dest_file, tmp_file, arguments->full_database_dir, + arguments->full_dss_dir, arguments->use_bitmap, arguments->is_retry); else @@ -1135,6 +1154,7 @@ merge_files(void *arg) arguments->dest_backup, dest_file, tmp_file, arguments->full_database_dir, + arguments->full_dss_dir, arguments->full_external_prefix); done: @@ -1281,6 +1301,7 @@ static void do_in_place_merge(merge_files_arg *arguments, //TODO: report in_place merge bytes. parray_append(arguments->merge_filelist, tmp_file); *iscontinue = true; + return; } } @@ -1368,7 +1389,8 @@ reorder_external_dirs(pgBackup *to_backup, parray *to_external, void merge_data_file(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup, pgFile *dest_file, pgFile *tmp_file, - const char *full_database_dir, bool use_bitmap, bool is_retry) + const char *full_database_dir, const char *full_dss_dir, + bool use_bitmap, bool is_retry) { FILE *out = NULL; char *buffer = (char *)pgut_malloc(STDIO_BUFSIZE); @@ -1383,7 +1405,10 @@ merge_data_file(parray *parent_chain, pgBackup *full_backup, */ /* set fullpath of destination file and temp files */ - join_path_components(to_fullpath, full_database_dir, tmp_file->rel_path); + if (is_dss_type(tmp_file->type)) + join_path_components(to_fullpath, full_dss_dir, tmp_file->rel_path); + else + join_path_components(to_fullpath, full_database_dir, tmp_file->rel_path); nRet = snprintf_s(to_fullpath_tmp1, MAXPGPATH, MAXPGPATH - 1, "%s_tmp1", to_fullpath); securec_check_ss_c(nRet, "\0", "\0"); nRet = snprintf_s(to_fullpath_tmp2, MAXPGPATH, MAXPGPATH - 1, "%s_tmp2", to_fullpath); @@ -1463,7 +1488,8 @@ merge_data_file(parray *parent_chain, pgBackup *full_backup, void merge_non_data_file(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup, pgFile *dest_file, pgFile *tmp_file, - const char *full_database_dir, const char *to_external_prefix) + const char *full_database_dir, const char *full_dss_dir, + const char *to_external_prefix) { size_t i = 0; char to_fullpath[MAXPGPATH]; @@ -1481,8 +1507,14 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup, dest_file->external_dir_num); join_path_components(to_fullpath, temp, dest_file->rel_path); } + else if (is_dss_type(dest_file->type)) + { + join_path_components(to_fullpath, full_dss_dir, dest_file->rel_path); + } else + { join_path_components(to_fullpath, full_database_dir, dest_file->rel_path); + } nRet = snprintf_s(to_fullpath_tmp, MAXPGPATH, MAXPGPATH - 1, "%s_tmp", to_fullpath); securec_check_ss_c(nRet, "\0", "\0"); @@ -1537,6 +1569,12 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup, join_path_components(from_fullpath, temp, from_file->rel_path); } + else if (is_dss_type(from_file->type)) + { + char backup_dss_dir[MAXPGPATH]; + join_path_components(backup_dss_dir, from_backup->root_dir, DSSDATA_DIR); + join_path_components(from_fullpath, backup_dss_dir, from_file->rel_path); + } else { char backup_database_dir[MAXPGPATH]; diff --git a/src/bin/pg_probackup/parsexlog.cpp b/src/bin/pg_probackup/parsexlog.cpp index ae896195f..c03d3e82c 100644 --- a/src/bin/pg_probackup/parsexlog.cpp +++ b/src/bin/pg_probackup/parsexlog.cpp @@ -439,9 +439,19 @@ validate_wal(pgBackup *backup, const char *archivedir, char backup_database_dir[MAXPGPATH]; char backup_xlog_path[MAXPGPATH]; - join_path_components(backup_database_dir, backup->root_dir, DATABASE_DIR); - join_path_components(backup_xlog_path, backup_database_dir, PG_XLOG_DIR); - + if (IsDssMode()) + { + errno_t rc; + join_path_components(backup_database_dir, backup->root_dir, DSSDATA_DIR); + rc = snprintf_s(backup_xlog_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s%d", + backup_database_dir, PG_XLOG_DIR, instance_config.dss.instance_id); + securec_check_ss_c(rc, "\0", "\0"); + } + else + { + join_path_components(backup_database_dir, backup->root_dir, DATABASE_DIR); + join_path_components(backup_xlog_path, backup_database_dir, PG_XLOG_DIR); + } validate_backup_wal_from_start_to_stop(backup, backup_xlog_path, tli, wal_seg_size); } diff --git a/src/bin/pg_probackup/pg_probackupb.h b/src/bin/pg_probackup/pg_probackupb.h index 3f36b73fa..56d19a24f 100644 --- a/src/bin/pg_probackup/pg_probackupb.h +++ b/src/bin/pg_probackup/pg_probackupb.h @@ -57,7 +57,7 @@ typedef struct pgFile_t int n_headers; /* number of blocks in the data file in backup */ pg_crc32 hdr_crc; /* CRC value of header file: name_hdr */ off_t hdr_off; /* offset in header map */ - int hdr_size; /* offset in header map */ + int hdr_size; /* the size of cpmpressed header */ device_type_t type; /* file device type */ } pgFile; @@ -250,6 +250,8 @@ struct pgBackup /* Size of data files in PGDATA at the moment of backup. */ int64 pgdata_bytes; + /* Size of data files in vgdata(DSS) at the moment of backup. */ + int64 dssdata_bytes; CompressAlg compress_alg; int compress_level; diff --git a/src/bin/pg_probackup/pg_probackupc.h b/src/bin/pg_probackup/pg_probackupc.h index 19b31d02a..93408264c 100644 --- a/src/bin/pg_probackup/pg_probackupc.h +++ b/src/bin/pg_probackup/pg_probackupc.h @@ -255,7 +255,8 @@ extern void create_data_directories(parray *dest_files, const char *backup_dir, bool extract_tablespaces, bool incremental, - fio_location location); + fio_location location, + bool is_restore); extern void read_tablespace_map(parray *files, const char *backup_dir); extern void opt_tablespace_map(ConfigOption *opt, const char *arg); @@ -390,6 +391,7 @@ extern void get_redo(const char *pgdata_path, RedoParams *redo); extern void parse_vgname_args(const char* args); extern bool is_ss_xlog(const char *ss_dir); extern void ss_createdir(const char *ss_dir, const char *vgdata, const char *vglog); +extern bool ss_create_if_pg_replication(pgFile *dir, const char *vgdata, const char *vglog); extern bool ss_create_if_doublewrite(pgFile* dir, const char* vgdata, int instance_id); extern bool ss_create_if_pg_replication(pgFile* dir, const char* vgdata, const char* vglog); extern char* xstrdup(const char* s); diff --git a/src/bin/pg_probackup/ptrack.cpp b/src/bin/pg_probackup/ptrack.cpp index f0fae365d..9d397d3f2 100644 --- a/src/bin/pg_probackup/ptrack.cpp +++ b/src/bin/pg_probackup/ptrack.cpp @@ -15,6 +15,7 @@ #endif #include "catalog/pg_tablespace.h" #include "common/fe_memutils.h" +#include "storage/file/fio_device.h" /* * Macro needed to parse ptrack. * NOTE Keep those values synchronized with definitions in ptrack.h @@ -234,6 +235,7 @@ make_pagemap_from_ptrack(parray *files, pgFile *file = (pgFile *) parray_get(files, file_i); page_map_entry **res_map = NULL; page_map_entry *map = NULL; + uint64 offset = 0; /* * For now nondata files are not entitled to have pagemap @@ -248,16 +250,28 @@ make_pagemap_from_ptrack(parray *files, continue; if (filemaps) { - dummy_map->path = file->rel_path; + int rc = 0; + char tmp_path[MAXPGPATH] = {0}; + // dummy_map->path = file->rel_path; if (file->compressed_file) { /* rel_path in filemaps is just oid without suffix of '_compress' */ - uint64 offset = strlen(file->rel_path) - strlen("_compress"); + offset = strlen(file->rel_path) - strlen("_compress"); file->rel_path[offset] = '\0'; - res_map = (page_map_entry **)parray_bsearch(filemaps, dummy_map, pgFileMapComparePath); - file->rel_path[offset] = '_'; - } else { - res_map = (page_map_entry **)parray_bsearch(filemaps, dummy_map, pgFileMapComparePath); } + + /* When enable dss, if the file is in VGNAME, the path needs to be an absolute path */ + if (is_dss_type(file->type)) { + rc = sprintf_s(tmp_path, sizeof(tmp_path), "%s/%s", + instance_config.dss.vgdata, file->rel_path); + securec_check_ss_c(rc, "\0", "\0"); + dummy_map->path = pgut_strdup(tmp_path); + } else { + dummy_map->path = file->rel_path; + } + res_map = (page_map_entry **)parray_bsearch(filemaps, dummy_map, pgFileMapComparePath); + + if (file->compressed_file) + file->rel_path[offset] = '_'; map = (res_map) ? *res_map : NULL; } diff --git a/src/bin/pg_probackup/restore.cpp b/src/bin/pg_probackup/restore.cpp index 25a139be6..a58312147 100644 --- a/src/bin/pg_probackup/restore.cpp +++ b/src/bin/pg_probackup/restore.cpp @@ -25,7 +25,7 @@ typedef struct { - parray *pgdata_files; + parray *pgdata_and_dssdata_files; parray *dest_files; pgBackup *dest_backup; parray *dest_external_dirs; @@ -60,7 +60,7 @@ static void restore_chain(pgBackup *dest_backup, parray *parent_chain, pgRestoreParams *params, const char *pgdata_path, const char *dssdata_path, bool no_sync); static void check_incremental_compatibility(const char *pgdata, uint64 system_identifier, - IncrRestoreMode incremental_mode); + IncrRestoreMode incremental_mode); static pgBackup *find_backup_range(parray *backups, time_t target_backup_id, pgRecoveryTarget *rt, @@ -70,11 +70,15 @@ static pgBackup * find_full_backup(parray *backups, pgBackup *dest_backup, const char *action); static XLogRecPtr determine_shift_lsn(pgBackup *dest_backup); -static void get_pgdata_files(const char *pgdata_path, - parray *pgdata_files, +static void get_pgdata_and_dssdata_files(const char *pgdata_path, + const char *dssdata_path, + parray *pgdata_and_dssdata_files, parray *external_dirs); +static bool skip_some_tblspc_files(pgFile *file); +static char check_in_dss_instance(pgFile *file, int include_id); static void remove_redundant_files(const char *pgdata_path, - parray *pgdata_files, + const char *dssdata_path, + parray *pgdata_and_dssdata_files, pgBackup *dest_backup, parray *external_dirs); static void threads_handle(pthread_t *threads, @@ -172,29 +176,40 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, elog(ERROR, "required parameter not specified: PGDATA (-D, --pgdata)"); + /* Check if restore destination empty : vgdata and vglog */ if (IsDssMode()) { - /* do not support increment restore in dss mode */ - if (params->incremental_mode != INCR_NONE) - { - elog(ERROR, "Incremental restore is not support when enable dss"); - } - if (!dir_is_empty(instance_config.dss.vgdata, FIO_DSS_HOST)) { + if (params->incremental_mode != INCR_NONE) + { + elog(INFO, "Running incremental restore into nonempty directory: \"%s\"", + instance_config.dss.vgdata); + } + else + { + elog(ERROR, "Restore destination is not empty: \"%s\"", + instance_config.dss.vgdata); + } dssdata_is_empty = false; - elog(ERROR, "Restore destination is not empty: \"%s\"", - instance_config.dss.vgdata); } if (!dir_is_empty(instance_config.dss.vglog, FIO_DSS_HOST)) { + if (params->incremental_mode != INCR_NONE) + { + elog(INFO, "Running incremental restore into nonempty directory: \"%s\"", + instance_config.dss.vglog); + } + else + { + elog(ERROR, "Restore destination is not empty: \"%s\"", + instance_config.dss.vglog); + } dssdata_is_empty = false; - elog(ERROR, "Restore destination is not empty: \"%s\"", - instance_config.dss.vglog); } } - /* Check if restore destination empty */ + /* Check if restore destination empty : PGDATA */ if (!dir_is_empty(instance_config.pgdata, FIO_DB_HOST)) { /* Check that remote system is NOT running and systemd id is the same as ours */ @@ -717,7 +732,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain, { int i; char timestamp[100]; - parray *pgdata_files = NULL; + parray *pgdata_and_dssdata_files = NULL; parray *dest_files = NULL; parray *external_dirs = NULL; /* arrays with meta info for multi threaded backup */ @@ -803,17 +818,18 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain, /* * Restore dest_backup internal directories. */ + create_data_directories(dest_files, instance_config.pgdata, dest_backup->root_dir, true, params->incremental_mode != INCR_NONE, - FIO_DB_HOST); + FIO_DB_HOST, true); /* some file is in dssserver */ if (IsDssMode()) create_data_directories(dest_files, instance_config.dss.vgdata, dest_backup->root_dir, true, params->incremental_mode != INCR_NONE, - FIO_DSS_HOST); + FIO_DSS_HOST, true); /* * Restore dest_backup external directories. @@ -836,9 +852,10 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain, /* Get list of files in destination directory and remove redundant files */ if (params->incremental_mode != INCR_NONE) { - pgdata_files = parray_new(); - get_pgdata_files(pgdata_path, pgdata_files, external_dirs); - remove_redundant_files(pgdata_path, pgdata_files, dest_backup, external_dirs); + pgdata_and_dssdata_files = parray_new(); + get_pgdata_and_dssdata_files(pgdata_path, dssdata_path, pgdata_and_dssdata_files, external_dirs); + remove_redundant_files(pgdata_path, dssdata_path, pgdata_and_dssdata_files, + dest_backup, external_dirs); } /* @@ -883,7 +900,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain, num_threads); threads_handle(threads, threads_args, dest_backup, dest_files, - pgdata_files, external_dirs, parent_chain, params, + pgdata_and_dssdata_files, external_dirs, parent_chain, params, pgdata_path, dssdata_path, use_bitmap, total_bytes); /* Close page header maps */ @@ -907,10 +924,10 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain, if (external_dirs != NULL) free_dir_list(external_dirs); - if (pgdata_files) + if (pgdata_and_dssdata_files) { - parray_walk(pgdata_files, pgFileFree); - parray_free(pgdata_files); + parray_walk(pgdata_and_dssdata_files, pgFileFree); + parray_free(pgdata_and_dssdata_files); } for (i = parray_num(parent_chain) - 1; i >= 0; i--) @@ -922,8 +939,9 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain, } } -static void get_pgdata_files(const char *pgdata_path, - parray *pgdata_files, +static void get_pgdata_and_dssdata_files(const char *pgdata_path, + const char *dssdata_path, + parray *pgdata_and_dssdata_files, parray *external_dirs) { char pretty_time[20]; @@ -933,11 +951,15 @@ static void get_pgdata_files(const char *pgdata_path, time(&start_time); if (fio_is_remote(FIO_DB_HOST)) - fio_list_dir(pgdata_files, pgdata_path, false, true, false, false, true, 0); + fio_list_dir(pgdata_and_dssdata_files, pgdata_path, false, true, false, false, true, 0); else - dir_list_file(pgdata_files, pgdata_path, + dir_list_file(pgdata_and_dssdata_files, pgdata_path, false, true, false, false, true, 0, FIO_LOCAL_HOST); + if (IsDssMode()) + dir_list_file(pgdata_and_dssdata_files, dssdata_path, + false, true, false, false, true, 0, FIO_DSS_HOST); + /* get external dirs content */ if (external_dirs) { @@ -954,12 +976,12 @@ static void get_pgdata_files(const char *pgdata_path, false, true, false, false, true, i+1, FIO_LOCAL_HOST); - parray_concat(pgdata_files, external_files); + parray_concat(pgdata_and_dssdata_files, external_files); parray_free(external_files); } } - parray_qsort(pgdata_files, pgFileCompareRelPathWithExternalDesc); + parray_qsort(pgdata_and_dssdata_files, pgFileCompareRelPathWithExternalDesc); time(&end_time); pretty_time_interval(difftime(end_time, start_time), @@ -983,13 +1005,52 @@ static bool skip_some_tblspc_files(pgFile *file) prefix_equ_tbs_version_dir = (strncmp(tmp_rel_path, TABLESPACE_VERSION_DIRECTORY, strlen(TABLESPACE_VERSION_DIRECTORY)) == 0); + /* In DSS mode, we should skip PG_9.2_201611171 */ + if (sscanf_res == 2 && IsDssMode() && prefix_equ_tbs_version_dir) + return true; + /* If the dss is not enabled, we should skip PG_9.2_201611171_node1 */ if (sscanf_res == 2 && !equ_tbs_version_dir && prefix_equ_tbs_version_dir) return true; return false; } +#define CHECK_FALSE 0 +#define CHECK_TRUE 1 +#define CHECK_EXCLUDE_FALSE 2 + +static char check_in_dss_instance(pgFile *file, int include_id) +{ + if (!is_dss_type(file->type)) { + return CHECK_TRUE; + } + + char instance_id[MAX_INSTANCEID_LEN]; + char top_path[MAXPGPATH]; + errno_t rc = EOK; + int move = 0; + + /* step1 : skip other instance owner file or dir */ + strlcpy(top_path, file->rel_path, sizeof(top_path)); + get_top_path(top_path); + + rc = snprintf_s(instance_id, sizeof(instance_id), sizeof(instance_id) - 1, "%d", include_id); + securec_check_ss_c(rc, "\0", "\0"); + + move = (int)strlen(top_path) - (int)strlen(instance_id); + if (move > 0 && move < MAXPGPATH && strcmp(top_path + move, instance_id) != 0) { + char tail = top_path[strlen(top_path) - 1]; + /* Is this file or dir belongs to other instance? */ + if (tail >= '0' && tail <= '9') { + return CHECK_FALSE; + } + } + + return CHECK_TRUE; +} + static void remove_redundant_files(const char *pgdata_path, - parray *pgdata_files, + const char *dssdata_path, + parray *pgdata_and_dssdata_files, pgBackup *dest_backup, parray *external_dirs) { @@ -998,8 +1059,8 @@ static void remove_redundant_files(const char *pgdata_path, elog(INFO, "Removing redundant files in destination directory"); time(&start_time); - for (int i = 0; (size_t)i < parray_num(pgdata_files); i++) { - pgFile *file = (pgFile *)parray_get(pgdata_files, i); + for (int i = 0; (size_t)i < parray_num(pgdata_and_dssdata_files); i++) { + pgFile *file = (pgFile *)parray_get(pgdata_and_dssdata_files, i); bool in_tablespace = false; /* For incremental backups, we need to skip some files */ @@ -1011,20 +1072,30 @@ static void remove_redundant_files(const char *pgdata_path, if (parray_bsearch(dest_backup->files, file, pgFileCompareRelPathWithExternal) == NULL) { char fullpath[MAXPGPATH]; + fio_location path_location; if (file->external_dir_num) { char *external_path = (char *)parray_get(external_dirs, file->external_dir_num - 1); join_path_components(fullpath, external_path, file->rel_path); + } else if (is_dss_type(file->type)) { + /* skip other instance files in dss mode */ + char check_res = check_in_dss_instance(file, instance_config.dss.instance_id); + if (check_res != CHECK_TRUE) { + continue; + } else { + join_path_components(fullpath, dssdata_path, file->rel_path); + } } else { join_path_components(fullpath, pgdata_path, file->rel_path); } - fio_delete(file->mode, fullpath, FIO_DB_HOST); + path_location = is_dss_type(file->type) ? FIO_DSS_HOST : FIO_DB_HOST; + fio_delete(file->mode, fullpath, path_location); elog(VERBOSE, "Deleted file \"%s\"", fullpath); /* shrink pgdata list */ - parray_remove(pgdata_files, i); + parray_remove(pgdata_and_dssdata_files, i); i--; } } @@ -1033,7 +1104,7 @@ static void remove_redundant_files(const char *pgdata_path, pretty_time_interval(difftime(end_time, start_time), pretty_time, lengthof(pretty_time)); - /* At this point PDATA do not contain files, that do not exists in dest backup file list */ + /* At this point PDATA and DSSDATA do not contain files, that do not exists in dest backup file list */ elog(INFO, "Redundant files are removed, time elapsed: %s", pretty_time); } @@ -1041,7 +1112,7 @@ static void threads_handle(pthread_t *threads, restore_files_arg *threads_args, pgBackup *dest_backup, parray *dest_files, - parray *pgdata_files, + parray *pgdata_and_dssdata_files, parray *external_dirs, parray *parent_chain, pgRestoreParams *params, @@ -1059,12 +1130,12 @@ static void threads_handle(pthread_t *threads, bool restore_isok = true; if (dest_backup->stream) - dest_bytes = dest_backup->pgdata_bytes + dest_backup->wal_bytes; + dest_bytes = dest_backup->pgdata_bytes + dest_backup->dssdata_bytes + dest_backup->wal_bytes; else - dest_bytes = dest_backup->pgdata_bytes; + dest_bytes = dest_backup->pgdata_bytes + dest_backup->dssdata_bytes; pretty_size(dest_bytes, pretty_dest_bytes, lengthof(pretty_dest_bytes)); - elog(INFO, "Start restoring backup files. PGDATA size: %s", pretty_dest_bytes); + elog(INFO, "Start restoring backup files. DATA size: %s", pretty_dest_bytes); time(&start_time); thread_interrupted = false; @@ -1074,7 +1145,7 @@ static void threads_handle(pthread_t *threads, restore_files_arg *arg = &(threads_args[i]); arg->dest_files = dest_files; - arg->pgdata_files = pgdata_files; + arg->pgdata_and_dssdata_files = pgdata_and_dssdata_files; arg->dest_backup = dest_backup; arg->dest_external_dirs = external_dirs; arg->parent_chain = parent_chain; @@ -1199,7 +1270,7 @@ inline void RestoreCompressFile(FILE *out, char *to_fullpath, pgFile *dest_file) } /* - * Restore files into $PGDATA. + * Restore files into $PGDATA and $VGNAME. */ static void * restore_files(void *arg) @@ -1272,7 +1343,7 @@ restore_files(void *arg) join_path_components(to_fullpath, arguments->to_root, dest_file->rel_path); if (arguments->incremental_mode != INCR_NONE && - parray_bsearch(arguments->pgdata_files, dest_file, pgFileCompareRelPathWithExternalDesc)) + parray_bsearch(arguments->pgdata_and_dssdata_files, dest_file, pgFileCompareRelPathWithExternalDesc)) { already_exists = true; } diff --git a/src/bin/pg_probackup/show.cpp b/src/bin/pg_probackup/show.cpp index 5acefda58..75995c541 100644 --- a/src/bin/pg_probackup/show.cpp +++ b/src/bin/pg_probackup/show.cpp @@ -471,6 +471,12 @@ print_backup_json_object(PQExpBuffer buf, pgBackup *backup) appendPQExpBuffer(buf, INT64_FORMAT, backup->pgdata_bytes); } + if (backup->uncompressed_bytes >= 0) + { + json_add_key(buf, "dssdata-bytes", json_level); + appendPQExpBuffer(buf, INT64_FORMAT, backup->dssdata_bytes); + } + if (backup->external_dir_str) json_add_value(buf, "external-dirs", backup->external_dir_str, json_level, true); diff --git a/src/bin/pg_probackup/util.cpp b/src/bin/pg_probackup/util.cpp index c7fa12452..80cccfd2f 100644 --- a/src/bin/pg_probackup/util.cpp +++ b/src/bin/pg_probackup/util.cpp @@ -551,7 +551,6 @@ bool is_ss_xlog(const char *ss_dir) { char ss_xlog[MAXPGPATH] = {0}; - char ss_doublewrite[MAXPGPATH] = {0}; char ss_notify[MAXPGPATH] = {0}; char ss_snapshots[MAXPGPATH] = {0}; int rc = EOK; @@ -588,6 +587,12 @@ ss_createdir(const char *ss_dir, const char *vgdata, const char *vglog) securec_check_ss_c(rc, "\0", "\0"); dir_create_dir(path, DIR_PERMISSION); + + /* if xlog link is already exist, destroy it and recreate */ + if (unlink(link_path) != 0) { + elog(ERROR, "can not remove xlog dir \"%s\" : %s", link_path, strerror(errno)); + } + if (symlink(path, link_path) < 0) { elog(ERROR, "can not link dss xlog dir \"%s\" to dss xlog dir \"%s\": %s", link_path, path, strerror(errno)); diff --git a/src/gausskernel/storage/access/transam/cbmparsexlog.cpp b/src/gausskernel/storage/access/transam/cbmparsexlog.cpp index af9c83c34..3c5739dab 100644 --- a/src/gausskernel/storage/access/transam/cbmparsexlog.cpp +++ b/src/gausskernel/storage/access/transam/cbmparsexlog.cpp @@ -50,6 +50,7 @@ #include "storage/proc.h" #include "utils/memutils.h" #include "utils/relmapper.h" +#include "storage/file/fio_device.h" /* we can put the following globals into XlogCbmSys */ static XLogRecPtr tmpTargetLSN = InvalidXLogRecPtr; @@ -929,9 +930,13 @@ static int CBMXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr XLogPageReadPrivateCBM *readprivate = (XLogPageReadPrivateCBM *)xlogreader->private_data; uint32 targetPageOff; int rc = 0; + char *dssdir = NULL; targetPageOff = targetPagePtr % XLogSegSize; + if (ENABLE_DSS) + dssdir = g_instance.attr.attr_storage.dss_attr.ss_dss_vg_name; + /* * See if we need to switch to a new segment because the requested record * is not in the currently open one. @@ -955,8 +960,17 @@ static int CBMXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr (uint32)((t_thrd.cbm_cxt.XlogCbmSys->xlogRead.logSegNo) % XLogSegmentsPerXLogId)); securec_check_ss(rc, "", ""); - rc = snprintf_s(t_thrd.cbm_cxt.XlogCbmSys->xlogRead.filePath, MAXPGPATH, MAXPGPATH - 1, "%s/" XLOGDIR "/%s", - readprivate->datadir, xlogfname); + if (ENABLE_DSS) { + char dss_xlog[MAXPGPATH]; + rc = snprintf_s(dss_xlog, MAXPGPATH, MAXPGPATH - 1, XLOGDIR "%d", + g_instance.attr.attr_storage.dms_attr.instance_id); + securec_check_ss(rc, "\0", "\0"); + rc = snprintf_s(t_thrd.cbm_cxt.XlogCbmSys->xlogRead.filePath, MAXPGPATH, MAXPGPATH - 1, + "%s/%s/%s", dssdir, dss_xlog, xlogfname); + } else { + rc = snprintf_s(t_thrd.cbm_cxt.XlogCbmSys->xlogRead.filePath, MAXPGPATH, MAXPGPATH - 1, + "%s/" XLOGDIR "/%s", readprivate->datadir, xlogfname); + } securec_check_ss(rc, "\0", "\0"); t_thrd.cbm_cxt.XlogCbmSys->xlogRead.fd = BasicOpenFile(t_thrd.cbm_cxt.XlogCbmSys->xlogRead.filePath, diff --git a/src/include/port.h b/src/include/port.h index a44a6b8e3..7ec3bcf4f 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -89,6 +89,8 @@ extern void pgfnames_cleanup(char** filenames); (isalpha((unsigned char)((filename)[0])) && (filename)[1] == ':' && IS_DIR_SEP((filename)[2]))) #endif +#define ss_is_absolute_path(filename) (((filename)[0] == '+') ? true : false) + /* Portable locale initialization (in exec.c) */ extern void set_pglocale_pgservice(const char* argv0, const char* app);