Update nas_am.cpp

This commit is contained in:
nuoya 2023-09-30 18:44:31 +08:00
parent 1dc7657220
commit b02deb9a95
1 changed files with 63 additions and 63 deletions

View File

@ -46,22 +46,22 @@
#include "postmaster/alarmchecker.h"
#include "replication/walreceiver.h"
//定义文件路径的最大长度,使代码更加清晰和易于维护
//定义文件路径的最大长度,使代码更加清晰和易于维护
#define MAX_PATH_LEN 1024
//定义了一个头部长度
//定义了一个头部长度
static int headerLen = 22;
// 定义一个函数用于从NAS存储中读取文件数据
// 定义一个函数用于从NAS存储中读取文件数据
size_t NasRead(const char* fileName, const int offset, char *buffer, const int length, ArchiveConfig *nas_config)
{
/*
fileName
offset
buffer
length
nas_config ArchiveConfig
fileName
offset
buffer
length
nas_config ArchiveConfig
*/
//初始化
//初始化
size_t readLength = 0;
ArchiveConfig *archive_nas = NULL;
char file_path[MAXPGPATH] = {0};
@ -69,45 +69,45 @@ size_t NasRead(const char* fileName, const int offset, char *buffer, const int l
FILE *fp = NULL;
struct stat statbuf;
if ((fileName == NULL) || (buffer == NULL)) {//如果文件名和缓冲区为空会报错
if ((fileName == NULL) || (buffer == NULL)) {//如果文件名和缓冲区为空会报错
ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("The parameter cannot be NULL")));
}
//获取NAS存储的配置信息
//获取NAS存储的配置信息
if (nas_config != NULL) {
archive_nas = nas_config;
} else {
archive_nas = getArchiveConfig();
}
if (archive_nas == NULL) {//无法获取归档配置信息时报错
if (archive_nas == NULL) {//无法获取归档配置信息时报错
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Cannot get archive config from replication slots")));
}
if (strncmp(fileName, "global_barrier_records", headerLen) != 0) {//构建文件的完整路径
//调用snprintf_s函数构建一个完整的文件路径并将结果存储在 file_path 变量中
if (strncmp(fileName, "global_barrier_records", headerLen) != 0) {//构建文件的完整路径
//调用snprintf_s函数构建一个完整的文件路径并将结果存储在 file_path 变量中
ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", archive_nas->archive_prefix, fileName);
// ret用于储存snprintf_s 函数的返回值。这个返回值表示已格式化字符串的长度。
securec_check_ss(ret, "\0", "\0");//如果发生错误将会在 ret 中返回 '\0' ,从而帮助定位错误的位置。
//用于检查 snprintf_s函数的返回值并进行安全性检查以确保没有发生缓冲区溢出或格式化错误
// ret用于储存snprintf_s 函数的返回值。这个返回值表示已格式化字符串的长度。
securec_check_ss(ret, "\0", "\0");//如果发生错误将会在 ret 中返回 '\0' ,从而帮助定位错误的位置。
//用于检查 snprintf_s函数的返回值并进行安全性检查以确保没有发生缓冲区溢出或格式化错误
} else {
char pathPrefix[MAXPGPATH] = {0};//生成一个空的char数组作为pathPrefix用于储存归档配置的存档前缀
char pathPrefix[MAXPGPATH] = {0};//生成一个空的char数组作为pathPrefix用于储存归档配置的存档前缀
ret = strcpy_s(pathPrefix, MAXPGPATH, archive_nas->archive_prefix);
//复制 archive_nas->archive_prefix 到 pathPrefix
//复制 archive_nas->archive_prefix 到 pathPrefix
securec_check_ss(ret, "\0", "\0");
if (!IS_PGXC_COORDINATOR) {
char *p = strrchr(pathPrefix, '/');//在pathPrefix中找到最后一个斜杠的位置
char *p = strrchr(pathPrefix, '/');//在pathPrefix中找到最后一个斜杠的位置
if (p == NULL) {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Obs path prefix is invalid")));
}
*p = '\0';//将最后一个斜杠替换为'\0'
*p = '\0';//将最后一个斜杠替换为'\0'
}
ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", pathPrefix, fileName);
securec_check_ss(ret, "\0", "\0");
// 构建完整路径并检查 snprintf_s 函数的返回值
// 构建完整路径并检查 snprintf_s 函数的返回值
}
//检查文件是否存在
//检查文件是否存在
if (stat(file_path, &statbuf)) {
if (errno != ENOENT) {
ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat file \"%s\": %m", fileName)));
@ -115,10 +115,10 @@ size_t NasRead(const char* fileName, const int offset, char *buffer, const int l
ereport(ERROR, (errcode_for_file_access(), errmsg("The file \"%s\" not exists", fileName)));
return readLength;
}
//打开文件并读取数据
//打开文件并读取数据
canonicalize_path(file_path);
fp = fopen(file_path, "rb");
//对于打开文件产生的错误进行处理
//对于打开文件产生的错误进行处理
if (fp == NULL) {
ereport(ERROR, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", fileName)));
return readLength;
@ -129,98 +129,98 @@ size_t NasRead(const char* fileName, const int offset, char *buffer, const int l
return readLength;
}
//读取数据到缓冲区中
//读取数据到缓冲区中
readLength = fread(buffer, 1, statbuf.st_size, fp);
fclose(fp);
return readLength;
}
//该函数用于将数据写入文件,并在必要时进行备份和重命名
//该函数用于将数据写入文件,并在必要时进行备份和重命名
int NasWrite(const char* fileName, const char *buffer, const int bufferLength, ArchiveConfig *nas_config)
{
int ret = 0;
ArchiveConfig *archive_nas = NULL;//存储NAS配置的指针
char file_path[MAXPGPATH] = {0};//存储构建的文件路
char file_path_bak[MAXPGPATH] = {0};//存储备份文件路径
char *origin_file_path = NULL;//存储规范化的文件路径的副本
char *base_path = NULL;//存储文件的基础路径
FILE *fp = NULL;//文件指针,用于操作文件
ArchiveConfig *archive_nas = NULL;//存储NAS配置的指针
char file_path[MAXPGPATH] = {0};//存储构建的文件路
char file_path_bak[MAXPGPATH] = {0};//存储备份文件路径
char *origin_file_path = NULL;//存储规范化的文件路径的副本
char *base_path = NULL;//存储文件的基础路径
FILE *fp = NULL;//文件指针,用于操作文件
//检查传入的参数是否为空,文件名和缓冲器为空时报错
//检查传入的参数是否为空,文件名和缓冲器为空时报错
if ((fileName == NULL) || (buffer == NULL)) {
ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("The parameter cannot be NULL")));
}
//获取归档配置信息如果传入的归档配置参数为NULL则尝试从默认位置获取
//获取归档配置信息如果传入的归档配置参数为NULL则尝试从默认位置获取
if (nas_config != NULL) {
archive_nas = nas_config;
} else {
archive_nas = getArchiveConfig();
}
//检查获取到的归档配置信息是否有效,无效时报错
//检查获取到的归档配置信息是否有效,无效时报错
if (archive_nas == NULL) {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Cannot get archive config from replication slots")));
}
//根据文件名构建完整的文件路径
if (strncmp(fileName, "global_barrier_records", headerLen) != 0) {//判断文件名是否为"global_barrier_records"
//根据文件名构建完整的文件路径
if (strncmp(fileName, "global_barrier_records", headerLen) != 0) {//判断文件名是否为"global_barrier_records"
ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", archive_nas->archive_prefix, fileName);
securec_check_ss(ret, "\0", "\0");
//构建完整路径并检查snprintf_s函数的返回值
//构建完整路径并检查snprintf_s函数的返回值
} else {
char pathPrefix[MAXPGPATH] = {0};//用于存储路径前缀
ret = strcpy_s(pathPrefix, MAXPGPATH, archive_nas->archive_prefix);//复制 archive_nas->archive_prefix 到 pathPrefix
char pathPrefix[MAXPGPATH] = {0};//用于存储路径前缀
ret = strcpy_s(pathPrefix, MAXPGPATH, archive_nas->archive_prefix);//复制 archive_nas->archive_prefix 到 pathPrefix
securec_check_ss(ret, "\0", "\0");
if (!IS_PGXC_COORDINATOR) {// 如果不是协调器节点
char *p = strrchr(pathPrefix, '/');//在pathPrefix中查找最后一个'/'
if (p == NULL) {//没有找到'/'则会报错
if (!IS_PGXC_COORDINATOR) {// 如果不是协调器节点
char *p = strrchr(pathPrefix, '/');//在pathPrefix中查找最后一个'/'
if (p == NULL) {//没有找到'/'则会报错
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Obs path prefix is invalid")));
}
*p = '\0';//将最后一个斜杠替换为'\0'
*p = '\0';//将最后一个斜杠替换为'\0'
}
ret = snprintf_s(file_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", pathPrefix, fileName);
securec_check_ss(ret, "\0", "\0");
// 构建完整路径并检查 snprintf_s 函数的返回值
// 构建完整路径并检查 snprintf_s 函数的返回值
}
canonicalize_path(file_path);//规范化文件路径,去除多余的字符,如'.'、'..'等
canonicalize_path(file_path);//规范化文件路径,去除多余的字符,如'.'、'..'等
origin_file_path = pstrdup(file_path);//复制文件路径到origin_file_path
base_path = dirname(origin_file_path);//获取origin_file_path文件的完整路径的父级路径即基础路径
//检查基础路径是否存在,如果不存在则创建
origin_file_path = pstrdup(file_path);//复制文件路径到origin_file_path
base_path = dirname(origin_file_path);//获取origin_file_path文件的完整路径的父级路径即基础路径
//检查基础路径是否存在,如果不存在则创建
if (!isDirExist(base_path)) {
// 调用 pg_mkdir_p 函数尝试创建目录S_IRWXU 是指定权限参数
if (pg_mkdir_p(base_path, S_IRWXU) != 0) {//如果返回值不为0则说明创建目录失败
// 如果创建目录失败,释放内存并报告错误
pfree_ext(origin_file_path);//释放其占用的内存空间
// 调用 pg_mkdir_p 函数尝试创建目录S_IRWXU 是指定权限参数
if (pg_mkdir_p(base_path, S_IRWXU) != 0) {//如果返回值不为0则说明创建目录失败
// 如果创建目录失败,释放内存并报告错误
pfree_ext(origin_file_path);//释放其占用的内存空间
ereport(LOG, (errmsg("could not create path \"%s\"", base_path)));
return -1;//返回 -1 表示创建目录失败
return -1;//返回 -1 表示创建目录失败
}
}
//构建备份文件的路径,将 ".bak" 添加到 file_path
//构建备份文件的路径,将 ".bak" 添加到 file_path
ret = snprintf_s(file_path_bak, MAXPGPATH, MAXPGPATH - 1, "%s.bak", file_path);
securec_check_ss(ret, "\0", "\0");
fp = fopen(file_path_bak, "wb");//打开备份文件,以二进制写入模式
if (fp == NULL) {//如果打开备份文件失败,释放内存并报告错误
fp = fopen(file_path_bak, "wb");//打开备份文件,以二进制写入模式
if (fp == NULL) {//如果打开备份文件失败,释放内存并报告错误
pfree_ext(origin_file_path);
ereport(LOG, (errmsg("could not create file \"%s\": %m", fileName)));
return -1;
}
//将数据写入备份文件
//将数据写入备份文件
if (fwrite(buffer, bufferLength, 1, fp) != 1) {
ereport(LOG, (errmsg("could not write file \"%s\": %m", fileName)));
pfree_ext(origin_file_path);
fclose(fp);
return -1;
}
//刷新文件缓冲区,确保数据写入磁盘
//刷新文件缓冲区,确保数据写入磁盘
if (fflush(fp) != 0) {
ereport(LOG, (errmsg("could not fflush file \"%s\": %m", fileName)));
(void)fclose(fp);
pfree_ext(origin_file_path);
return -1;
}
//将备份文件重命名为正式文件
//将备份文件重命名为正式文件
if (rename(file_path_bak, file_path) < 0) {
ereport(LOG, (errmsg("could not rename file \"%s\": %m", fileName)));
(void)fclose(fp);
@ -228,8 +228,8 @@ int NasWrite(const char* fileName, const char *buffer, const int bufferLength, A
return -1;
}
pfree_ext(origin_file_path);//释放被占用的内存空间
fclose(fp);//关闭文件
pfree_ext(origin_file_path);//释放被占用的内存空间
fclose(fp);//关闭文件
return 0;
}