资源池化适配gs_probackup

This commit is contained in:
liuzhanfeng2
2023-11-20 17:06:34 +08:00
parent b2d32fa740
commit 1d9a3e4773
13 changed files with 375 additions and 145 deletions

View File

@ -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(&current, 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(&current, pg_wal_dir, lengthof(pg_wal_dir),
DSSDATA_DIR, dss_xlog);
}
else
{
pgBackupGetPath2(&current, 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

View File

@ -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,

View File

@ -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)
{

View File

@ -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];

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -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,

View File

@ -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);