diff --git a/src/gausskernel/storage/smgr/mmap_shared.cpp b/src/gausskernel/storage/smgr/mmap_shared.cpp index 4d8c85c73..02aee4c38 100644 --- a/src/gausskernel/storage/smgr/mmap_shared.cpp +++ b/src/gausskernel/storage/smgr/mmap_shared.cpp @@ -54,96 +54,148 @@ static inline pthread_mutex_t *MmapPartitionLock(size_t hashCode) { return &mmapLockArray[hashCode % LOCK_ARRAY_SIZE]; } - +/* + * 功能:同步页压缩内存映射的数据到磁盘 + * + * 参数列表: + * pcMap:PageCompressHeader 结构的指针,表示页压缩内存映射的头部信息 + * wait_event_info:一个表示等待事件的标识,用于记录等待事件的类型 + */ static inline PageCompressHeader *MmapSharedMapFile(Vfd *vfdP, uint16 chunkSize, uint2 opt, bool readonly) { + // 调用 pc_mmap_real_size 函数映射共享内存文件,返回一个指向 PageCompressHeader 结构体的指针 map。 auto map = pc_mmap_real_size(vfdP->fd, SIZE_OF_PAGE_COMPRESS_ADDR_FILE(chunkSize), false); + // 检查映射的文件区域是否有效,若无效则进行初始化设置。 if (map->chunk_size == 0 || map->algorithm == 0) { + // 检查映射的文件区域是否有效,若无效则进行初始化设置。 map->chunk_size = chunkSize; map->algorithm = GET_COMPRESS_ALGORITHM(opt); + // 使用 pc_msync 函数将映射区域的数据同步到文件中。 if (pc_msync(map) != 0) { + // 如果同步失败,则生成错误报告。 ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), errmsg("could not msync file \"%s\": %m", vfdP->fileName))); } } + // 如果正在进行恢复操作且映射区域未同步,则调用 CheckAndRepairCompressAddress 函数进行检查和修复。 if (RecoveryInProgress() && !map->sync) { CheckAndRepairCompressAddress(map, chunkSize, map->algorithm, vfdP->fileName); } + // 返回映射区域的指针 map。 return map; } - +/* + * 功能:初始化页压缩内存映射的锁数组 + */ void RealInitialMMapLockArray() { + // 遍历锁数组,为每个元素初始化一个互斥锁 for (size_t i = 0; i < LOCK_ARRAY_SIZE; ++i) { pthread_mutex_init(&mmapLockArray[i], NULL); } - + // 初始化哈希表控制结构体 HASHCTL ctl; /* hash accessed by database file id */ + // 使用 memset_s 函数将 ctl 结构体清零 errno_t rc = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check(rc, "", ""); - + // 设置哈希键的大小和每个条目的大小 ctl.keysize = sizeof(RelFileNodeForkNum); ctl.entrysize = sizeof(MmapEntry); ctl.hash = tag_hash; ctl.num_partitions = LOCK_ARRAY_SIZE; const size_t initLen = 256; + // 初始化内存哈希表,用于页压缩内存映射的缓存 g_instance.mmapCache = HeapMemInitHash( "mmap hash", initLen, (Max(g_instance.attr.attr_common.max_files_per_process, t_thrd.storage_cxt.max_userdatafiles)) / 2, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_PARTITION); } - +/* + * 功能:获取页压缩内存映射的头部信息 + * + * 参数列表: + * vfd:指向文件描述符信息的指针 + * chunkSize:uint16 类型,表示页面压缩的块大小 + * relFileNodeForkNum:RelFileNodeForkNum 结构,表示文件的标识信息 + */ PageCompressHeader *GetPageCompressHeader(void *vfd, uint16 chunkSize, const RelFileNodeForkNum &relFileNodeForkNum) { + // 将传入的 vfd 转换为 Vfd 结构体指针 Vfd *currentVfd = (Vfd *)vfd; + // 计算哈希码以用于锁分区 uint32 hashCode = MmapTableHashCode(relFileNodeForkNum); + // 使用 AutoMutexLock 自动加锁,锁定相应的分区 AutoMutexLock mmapLock(MmapPartitionLock(hashCode)); - + // 加锁 mmapLock.lock(); + // 初始化查找结果标志 bool find = false; + // 在内存哈希表中搜索文件标识,并返回相应的 MmapEntry 结构指针 MmapEntry *mmapEntry = (MmapEntry *)hash_search_with_hash_value(g_instance.mmapCache, (void *)&relFileNodeForkNum, hashCode, HASH_ENTER, &find); + // 如果未找到对应条目,则进行初始化设置 if (!find) { mmapEntry->pcmap = NULL; mmapEntry->reference = 0; } + // 如果 pcmap 为空,则调用 MmapSharedMapFile 函数映射文件 if (mmapEntry->pcmap == NULL) { mmapEntry->pcmap = MmapSharedMapFile(currentVfd, chunkSize, relFileNodeForkNum.rnode.node.opt, false); } + // 增加对映射区域的引用计数 ++mmapEntry->reference; + // 增加对映射区域的引用计数 mmapLock.unLock(); + // 返回映射区域的指针 return mmapEntry->pcmap; } - +/* + * 功能:解除页压缩内存映射的引用计数,并在不再使用时释放资源 + * + * 参数列表: + * vfd:指向文件描述符信息的指针 + */ void UnReferenceAddrFile(void *vfd) { + // 将传入的 vfd 转换为 Vfd 结构体指针 Vfd *currentVfd = (Vfd *)vfd; + // 获取文件标识信息 RelFileNodeForkNum relFileNodeForkNum = currentVfd->fileNode; + // 计算哈希码以用于锁分区 uint32 hashCode = MmapTableHashCode(relFileNodeForkNum); + // 使用 AutoMutexLock 自动加锁,锁定相应的分区 AutoMutexLock mmapLock(MmapPartitionLock(hashCode)); mmapLock.lock(); + // 在内存哈希表中搜索文件标识,并返回相应的 MmapEntry 结构指针(HASH_FIND 模式) MmapEntry *mmapEntry = (MmapEntry *)hash_search_with_hash_value(g_instance.mmapCache, (void *)&relFileNodeForkNum, hashCode, HASH_FIND, NULL); + // 如果没有找到对应的条目,则生成错误报告 if (mmapEntry == NULL) { ereport(ERROR, (errcode_for_file_access(), errmsg("UnReferenceAddrFile failed! mmap not found, filePath: %s", currentVfd->fileName))); } + // 减少对映射区域的引用计数 --mmapEntry->reference; + // 如果引用计数降为零,释放资源 if (mmapEntry->reference == 0) { + // 调用 pc_munmap 函数释放映射区域的资源 if (pc_munmap(mmapEntry->pcmap) != 0) { ereport(ERROR, (errcode_for_file_access(), errmsg("could not munmap file \"%s\": %m", currentVfd->fileName))); } + // 从内存哈希表中移除对应的哈希键 if (hash_search_with_hash_value(g_instance.mmapCache, (void *)&relFileNodeForkNum, hashCode, HASH_REMOVE, NULL) == NULL) { ereport(ERROR, (errcode_for_file_access(), errmsg("UnReferenceAddrFile failed! remove hash key failed, filePath: %s", currentVfd->fileName))); } - } else if (mmapEntry->reference < 0) { + } + // 如果引用计数小于零,生成致命错误报告 + else if (mmapEntry->reference < 0) { ereport(FATAL, (errcode_for_file_access(), errmsg("could not munmap file \"%s\": %m", currentVfd->fileName))); } - mmapLock.unLock(); + mmapLock.unLock(); // 解锁 } \ No newline at end of file