diff --git a/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp b/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp index 917f63303..2dcaae232 100644 --- a/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp +++ b/src/gausskernel/ddes/adapter/ss_dms_bufmgr.cpp @@ -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; } diff --git a/src/gausskernel/ddes/adapter/ss_dms_callback.cpp b/src/gausskernel/ddes/adapter/ss_dms_callback.cpp index 24cf0ffd5..e7cb2ad11 100644 --- a/src/gausskernel/ddes/adapter/ss_dms_callback.cpp +++ b/src/gausskernel/ddes/adapter/ss_dms_callback.cpp @@ -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) { diff --git a/src/gausskernel/storage/smgr/segment/data_file.cpp b/src/gausskernel/storage/smgr/segment/data_file.cpp index f20810f47..523c83f3b 100644 --- a/src/gausskernel/storage/smgr/segment/data_file.cpp +++ b/src/gausskernel/storage/smgr/segment/data_file.cpp @@ -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++) { diff --git a/src/gausskernel/storage/smgr/segment/extent_group.cpp b/src/gausskernel/storage/smgr/segment/extent_group.cpp index b472a35db..ddfb334a2 100644 --- a/src/gausskernel/storage/smgr/segment/extent_group.cpp +++ b/src/gausskernel/storage/smgr/segment/extent_group.cpp @@ -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; } diff --git a/src/gausskernel/storage/smgr/segment/space.cpp b/src/gausskernel/storage/smgr/segment/space.cpp index 9de167b89..122ff7884 100644 --- a/src/gausskernel/storage/smgr/segment/space.cpp +++ b/src/gausskernel/storage/smgr/segment/space.cpp @@ -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); +} diff --git a/src/include/ddes/dms/ss_common_attr.h b/src/include/ddes/dms/ss_common_attr.h index 59b933d2f..413a33528 100644 --- a/src/include/ddes/dms/ss_common_attr.h +++ b/src/include/ddes/dms/ss_common_attr.h @@ -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, diff --git a/src/include/storage/smgr/segment.h b/src/include/storage/smgr/segment.h index 578cfea32..8cb73ac3e 100644 --- a/src/include/storage/smgr/segment.h +++ b/src/include/storage/smgr/segment.h @@ -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