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