解决备机异常触发reform后,主机跑业务会卡死的问题
This commit is contained in:
@ -944,5 +944,5 @@ long SSGetBufSleepTime(int retry_times)
|
||||
if (retry_times < ss_buf_retry_threshold) {
|
||||
return 5000L * retry_times;
|
||||
}
|
||||
return 1000L * 1000 * 60;
|
||||
return 1000L * 1000 * 20;
|
||||
}
|
||||
|
@ -1327,7 +1327,8 @@ static int CBConfirmOwner(void *db_handle, char *pageid, unsigned char *lock_mod
|
||||
|
||||
SSGetBufferDesc(pageid, &valid, &buf_desc);
|
||||
if (buf_desc == NULL) {
|
||||
return DMS_ERROR;
|
||||
*lock_mode = (uint8)DMS_LOCK_NULL;
|
||||
return GS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
@ -1364,7 +1365,8 @@ static int CBConfirmConverting(void *db_handle, char *pageid, unsigned char smon
|
||||
|
||||
SSGetBufferDesc(pageid, &valid, &buf_desc);
|
||||
if (buf_desc == NULL) {
|
||||
return DMS_ERROR;
|
||||
*lock_mode = (uint8)DMS_LOCK_NULL;
|
||||
return GS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
|
@ -61,19 +61,24 @@ static int dv_open_file(char *filename, uint32 flags, int mode)
|
||||
|
||||
static void dv_close_file(int fd)
|
||||
{
|
||||
close(fd);
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
}
|
||||
ereport(LOG, (errmsg("dv_close_file fd is %d", fd)));
|
||||
}
|
||||
|
||||
/* Return a palloc string, and callers should free it */
|
||||
static char *slice_filename(const char *filename, int sliceno)
|
||||
{
|
||||
char *res = (char *)palloc(MAXPGPATH);
|
||||
char *res = NULL;
|
||||
int len = strlen(filename);
|
||||
if (sliceno == 0) {
|
||||
errno_t rc = snprintf_s(res, MAXPGPATH, MAXPGPATH - 1, "%s", filename);
|
||||
res = (char *)palloc(len + 1);
|
||||
errno_t rc = sprintf_s(res, len + 1, "%s", filename);
|
||||
securec_check_ss(rc, "\0", "\0");
|
||||
} else {
|
||||
errno_t rc = snprintf_s(res, MAXPGPATH, MAXPGPATH - 1, "%s.%d", filename, sliceno);
|
||||
res = (char *)palloc(len + MAX_LEN_OF_MAXINTRANGE);
|
||||
errno_t rc = sprintf_s(res, len + MAX_LEN_OF_MAXINTRANGE, "%s.%d", filename, sliceno);
|
||||
securec_check_ss(rc, "\0", "\0");
|
||||
}
|
||||
return res;
|
||||
@ -154,28 +159,34 @@ bool df_ss_update_segfile_size(SegLogicFile *sf, BlockNumber target_block)
|
||||
char *filename = slice_filename(sf->filename, 0);
|
||||
int fd = dv_open_file(filename, flags, (int)SEGMENT_FILE_MODE);
|
||||
if (fd < 0) {
|
||||
pfree(filename);
|
||||
ereport(LOG,
|
||||
(errmodule(MOD_SEGMENT_PAGE), errmsg("File \"%s\" does not exist, stop read here.", filename)));
|
||||
pfree(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
sf->file_num++;
|
||||
sf->segfiles[0].fd = fd;
|
||||
sf->segfiles[0].sliceno = 0;
|
||||
pfree(filename);
|
||||
}
|
||||
|
||||
int sliceno = sf->file_num - 1;
|
||||
int fd = sf->segfiles[sliceno].fd;
|
||||
if (fd <= 0) {
|
||||
char *filename = slice_filename(sf->filename, sliceno);
|
||||
sf->segfiles[sliceno].fd = dv_open_file(filename, flags, SEGMENT_FILE_MODE);
|
||||
fd = sf->segfiles[sliceno].fd;
|
||||
pfree(filename);
|
||||
}
|
||||
off_t size = lseek(fd, 0L, SEEK_END);
|
||||
sf->total_blocks = (uint32)(sliceno * DF_FILE_SLICE_BLOCKS + size / BLCKSZ); /* size of full slices + last slice */
|
||||
|
||||
while (size == DF_FILE_SLICE_SIZE) {
|
||||
sliceno = sf->file_num;
|
||||
char *filename = slice_filename(sf->filename, sf->file_num); /* needed if primary created new slice */
|
||||
if (sliceno >= sf->vector_capacity) {
|
||||
df_extend_file_vector(sf);
|
||||
}
|
||||
char *filename = slice_filename(sf->filename, sliceno);
|
||||
fd = dv_open_file(filename, flags, (int)SEGMENT_FILE_MODE);
|
||||
if (fd < 0) {
|
||||
ereport(LOG,
|
||||
@ -190,12 +201,13 @@ bool df_ss_update_segfile_size(SegLogicFile *sf, BlockNumber target_block)
|
||||
size = lseek(fd, 0L, SEEK_END);
|
||||
sf->total_blocks += (uint32)(size / BLCKSZ);
|
||||
sf->file_num++;
|
||||
pfree(filename);
|
||||
}
|
||||
|
||||
if (sf->total_blocks <= target_block) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -220,6 +232,11 @@ SegPhysicalFile df_get_physical_file(SegLogicFile *sf, int sliceno, BlockNumber
|
||||
}
|
||||
|
||||
SegmentCheck(sliceno < sf->file_num);
|
||||
if (SS_STANDBY_MODE && sf->segfiles[sliceno].fd <= 0) {
|
||||
char *filename = slice_filename(sf->filename, sliceno);
|
||||
sf->segfiles[sliceno].fd = dv_open_file(filename, O_RDONLY | PG_BINARY, SEGMENT_FILE_MODE);
|
||||
pfree(filename);
|
||||
}
|
||||
|
||||
SegPhysicalFile spf = sf->segfiles[sliceno];
|
||||
return spf;
|
||||
@ -258,7 +275,7 @@ void df_extend_file_vector(SegLogicFile *sf)
|
||||
{
|
||||
int new_capacity = sf->vector_capacity + DF_ARRAY_EXTEND_STEP;
|
||||
MemoryContext oldcnxt = MemoryContextSwitchTo(INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE));
|
||||
SegPhysicalFile *newfiles = (SegPhysicalFile *)palloc(sizeof(SegPhysicalFile) * new_capacity);
|
||||
SegPhysicalFile *newfiles = (SegPhysicalFile *)palloc0(sizeof(SegPhysicalFile) * new_capacity);
|
||||
MemoryContextSwitchTo(oldcnxt);
|
||||
|
||||
for (int i = 0; i < sf->file_num; i++) {
|
||||
|
@ -109,7 +109,9 @@ void eg_init_df_ctrl(SegExtentGroup *seg)
|
||||
SegLogicFile *sf = (SegLogicFile *)palloc(sizeof(SegLogicFile));
|
||||
MemoryContextSwitchTo(oldcnxt);
|
||||
df_ctrl_init(sf, seg->rnode, seg->forknum);
|
||||
df_open_files(sf);
|
||||
if (!SS_STANDBY_MODE) {
|
||||
df_open_files(sf);
|
||||
}
|
||||
|
||||
seg->segfile = sf;
|
||||
}
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "storage/file/fio_device.h"
|
||||
#include "libaio.h"
|
||||
|
||||
static void SSInitSegLogicFile(SegSpace *spc);
|
||||
|
||||
void spc_lock(SegSpace *spc)
|
||||
{
|
||||
PthreadMutexLock(t_thrd.utils_cxt.CurrentResourceOwner, &spc->lock, true);
|
||||
@ -241,6 +243,10 @@ void InitSpaceNode(SegSpace *spc, Oid spcNode, Oid dbNode, bool is_redo)
|
||||
eg_ctrl_init(spc, &spc->extent_group[egid][forknum], EXTENT_GROUPID_TO_SIZE(egid), forknum);
|
||||
}
|
||||
}
|
||||
|
||||
if (SS_STANDBY_MODE) {
|
||||
SSInitSegLogicFile(spc);
|
||||
}
|
||||
}
|
||||
|
||||
void spc_clean_extent_groups(SegSpace *spc)
|
||||
@ -1353,3 +1359,153 @@ void InitSegSpcCache(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool SSCheckIfSegLogicFileNormal(SegExtentGroup *seg)
|
||||
{
|
||||
SegLogicFile *sf = seg->segfile;
|
||||
if (sf->total_blocks < DF_FILE_MIN_BLOCKS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = BasicOpenFile(sf->filename, O_RDWR | PG_BINARY, S_IWUSR | S_IRUSR);
|
||||
if (fd < 0) {
|
||||
ereport(ERROR, (errmsg("open_file failed filename: %s, fd is %d, %d", sf->filename, fd, errno)));
|
||||
}
|
||||
sf->segfiles[0].fd = fd;
|
||||
char* buffer = (char *)palloc(BLCKSZ + ALIGNOF_BUFFER);
|
||||
char* aligned_buffer = (char *)BUFFERALIGN(buffer);
|
||||
int nbytes = pread(fd, aligned_buffer, BLCKSZ, DF_MAP_HEAD_PAGE * BLCKSZ);
|
||||
if (nbytes != BLCKSZ) {
|
||||
ereport(ERROR, (errmsg("could not read segment meta block in file %s, %d", sf->filename, errno)));
|
||||
}
|
||||
|
||||
if (!PageIsVerified((Page)aligned_buffer, DF_MAP_HEAD_PAGE)) {
|
||||
pfree(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
df_map_head_t *map_head = (df_map_head_t *)PageGetContents((Page)aligned_buffer);
|
||||
if (map_head->bit_unit != seg->extent_size) {
|
||||
pfree(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
pfree(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SSUpdateSegLogicFileSize(SegSpace *spc)
|
||||
{
|
||||
bool is_normal = true;
|
||||
bool is_meta_normal = false;
|
||||
|
||||
for (int egid = 0; egid < EXTENT_GROUPS; egid++) {
|
||||
for (int forknum = 0; forknum <= SEGMENT_MAX_FORKNUM; forknum++) {
|
||||
SegLogicFile *sf = spc->extent_group[egid][forknum].segfile;
|
||||
if (sf->file_num == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct stat statbuf;
|
||||
if (sf->file_num == 1) {
|
||||
if (stat(sf->filename, &statbuf) == 0) {
|
||||
sf->total_blocks = statbuf.st_size / BLCKSZ;
|
||||
} else {
|
||||
ereport(ERROR, (errmsg("failed stat file %s during init segment file.", sf->filename)));
|
||||
}
|
||||
} else {
|
||||
char fullpath[MAXPGPATH];
|
||||
errno_t rc = sprintf_s(fullpath, MAXPGPATH, "%s.%d", sf->filename, sf->file_num - 1);
|
||||
securec_check_ss(rc, "\0", "\0");
|
||||
if (stat(fullpath, &statbuf) == 0) {
|
||||
sf->total_blocks = statbuf.st_size / BLCKSZ + (sf->file_num - 1) * EXT_SIZE_1024_TOTAL_PAGES;
|
||||
} else {
|
||||
ereport(ERROR, (errmsg("failed stat file %s during init segment file.", fullpath)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_normal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we can set spc status to open here, only need to open sf->filename and read one block to verify */
|
||||
if (is_normal && SSCheckIfSegLogicFileNormal(&(spc->extent_group[egid][forknum]))) {
|
||||
if (egid == 0 && forknum == 0) {
|
||||
is_meta_normal = true;
|
||||
}
|
||||
} else {
|
||||
is_normal = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_meta_normal && is_normal) {
|
||||
spc->status = OPENED;
|
||||
}
|
||||
}
|
||||
|
||||
static void SSUpdateSegLogicFileNum(SegLogicFile* sf, char* dirpath, char* filename)
|
||||
{
|
||||
int sliceno = sf->file_num + 1;
|
||||
if (sliceno > sf->vector_capacity) {
|
||||
df_extend_file_vector(sf);
|
||||
}
|
||||
sf->segfiles[sf->file_num].sliceno = sf->file_num;
|
||||
sf->file_num++;
|
||||
}
|
||||
|
||||
static void SSInitSegLogicFile(SegSpace *spc)
|
||||
{
|
||||
if (spc->extent_group[0][0].segfile == NULL) {
|
||||
return;
|
||||
}
|
||||
SegmentCheck(spc->extent_group[0][0].segfile->filename[0] != '\0');
|
||||
/* Get path of dir from seg filename */
|
||||
char dirpath[MAXPGPATH];
|
||||
int count = strlen(spc->extent_group[0][0].segfile->filename) - SEG_MAINFORK_FILENAME_LEN;
|
||||
int rc = EOK;
|
||||
rc = strncpy_s(dirpath, MAXPGPATH, spc->extent_group[0][0].segfile->filename, count);
|
||||
securec_check_c(rc, "\0", "\0");
|
||||
|
||||
/*
|
||||
* Read dir and fill seg logic file except fd.
|
||||
* For filenum and total block, we only need to check the filename and size under the dir.
|
||||
* For fd, we can construct the filename and open it when we really need use the file.
|
||||
*/
|
||||
DIR *data_dir = NULL;
|
||||
struct dirent *data_de = NULL;
|
||||
data_dir = opendir(dirpath);
|
||||
if (data_dir == NULL) {
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(), errmsg("could not open data dir %s during init segment file.", dirpath)));
|
||||
}
|
||||
|
||||
while ((data_de = readdir(data_dir)) != NULL) {
|
||||
if (!isdigit(data_de->d_name[0])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char tmp_path[MAXPGPATH];
|
||||
int suffix = 0;
|
||||
rc = sscanf_s(data_de->d_name, "%[^.].%d", tmp_path, MAXPGPATH, &suffix);
|
||||
if (rc <= 0) {
|
||||
ereport(LOG, (errmsg("skip %s as it is not segment file.", data_de->d_name)));
|
||||
continue;
|
||||
}
|
||||
int extent_size = tmp_path[0] - '0';
|
||||
int tmp_length = strlen(tmp_path);
|
||||
if (strstr(tmp_path, "_vm") != NULL && tmp_length == SEG_VMFORK_FILENAME_LEN && extent_size >= EXTENT_1 &&
|
||||
extent_size <= EXTENT_8192) {
|
||||
SSUpdateSegLogicFileNum(spc->extent_group[extent_size - 1][VISIBILITYMAP_FORKNUM].segfile, dirpath,
|
||||
data_de->d_name);
|
||||
} else if (strstr(tmp_path, "_fsm") != NULL && tmp_length == SEG_FSMFORK_FILENAME_LEN &&
|
||||
extent_size >= EXTENT_1 && extent_size <= EXTENT_8192) {
|
||||
SSUpdateSegLogicFileNum(spc->extent_group[extent_size - 1][FSM_FORKNUM].segfile, dirpath, data_de->d_name);
|
||||
} else if (tmp_length == 1 && extent_size >= EXTENT_1 && extent_size <= EXTENT_8192) {
|
||||
SSUpdateSegLogicFileNum(spc->extent_group[extent_size - 1][MAIN_FORKNUM].segfile, dirpath, data_de->d_name);
|
||||
} else {
|
||||
ereport(LOG, (errmsg("skip %s as it is not segment file.", data_de->d_name)));
|
||||
}
|
||||
}
|
||||
SSUpdateSegLogicFileSize(spc);
|
||||
closedir(data_dir);
|
||||
}
|
||||
|
@ -191,6 +191,16 @@
|
||||
#define DMS_MSG_MAX_WAIT_TIME (10 * 1000) // 10s
|
||||
#define SS_REFORM_WAIT_TIME (5000) // 5ms
|
||||
|
||||
/* length of segment filename like '/1' */
|
||||
#define SEG_MAINFORK_FILENAME_LEN 2
|
||||
/* length of segment vm filename like '1_vm' */
|
||||
#define SEG_VMFORK_FILENAME_LEN 4
|
||||
/* length of segment fsm filename like '1_fsm' */
|
||||
#define SEG_FSMFORK_FILENAME_LEN 5
|
||||
|
||||
/* max length of max int range as char */
|
||||
#define MAX_LEN_OF_MAXINTRANGE 12
|
||||
|
||||
typedef enum SSBroadcastOp {
|
||||
BCAST_CANCEL_TRX_FOR_SWITCHOVER = 0,
|
||||
BCAST_SI,
|
||||
|
@ -67,6 +67,7 @@ int seg_sync_filetag(const FileTag *ftag, char *path);
|
||||
int seg_unlink_filetag(const FileTag *ftag, char *path);
|
||||
void segForgetDatabaseFsyncRequests(Oid dbid);
|
||||
bool seg_filetag_matches(const FileTag *ftag, const FileTag *candidate);
|
||||
void df_extend_file_vector(SegLogicFile *sf);
|
||||
|
||||
/*
|
||||
* XLog Atomic Operation APIs
|
||||
|
Reference in New Issue
Block a user