加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【原】Postgresql源码中的动态Hash(hash_search)调用方法详解

(2017-03-29 20:59:43)
标签:

postgresql

postgres

数据库

哈希表

hash

分类: Postgres和数据库
Postgresql 中的hash表是经常使用的一种结构
本文主要讨论下PG中的hash表的实现原理和使用方法
 
1) 设计实现:
 
源码中的评论如下:

 
说明这些函数是模仿系统的hsearch 函数实现的

 
2) 调用和注意事项:
2.1) 创建hash表:
   DeparseFlatInfo* info;
   MemoryContext old_mem;
   HASHCTL ctl;

   old_mem = MemoryContextSwitchTo(context);
   info = palloc0(sizeof(*info));
   info->deparse_ctx = context;
   info->serveroid = serv_id;
   info->estate = estate;
   info->top_plan =  copyObject(top_plan);
   info->old_ctx = old_mem;

   MemSet(&ctl, 0, sizeof(ctl));
   
   ctl.entrysize = sizeof(PlanFlatDeparse);
   ctl.keysize = sizeof(void*);
   ctl.hash = tag_hash;
   ctl.hcxt = info->deparse_ctx;
   info->plan_hash = hash_create("plan to DeparseFlatInfo", 31, &ctl
                                 , HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);

   
   (void)MemoryContextSwitchTo(old_mem);


2.2) 插入条目
   #define InsertDeparseUseHTAB(node_, hashp_, found) hash_search(hashp_, (void*)&node_, HASH_ENTER, found)
   deparse = InsertDeparseUseHTAB(plan, flat_info->plan_hash, &found);
   if(!deparse)
       return NULL;
   if(found)
       return deparse;
   Assert(deparse->plan == plan);
   MemSet(deparse, 0, sizeof(*deparse));
   deparse->plan = (void*)plan;
   deparse->parent = parent;
   deparse->flat_info = flat_info;

2.3)查找条目
PlanDeparse* GetDeparseUseHTAB(Node *node, HTAB *hash)
{
   PlanDeparse *deparse;
   bool find;
   Assert(node != NULL && hash != NULL);
   deparse = hash_search(hash, (void*)&node, HASH_FIND, &find);
   if(find)
       return deparse;
   return NULL;
}
#define GetDeparseUseDeparseInfo(_node, _info) GetDeparseUseHTAB(((Node*)(_node)), (_info)->plan_hash)
DeparseFlatInfo *flat_info;
Plan * this_plan;
PlanFlatDeparse *this_deparse =NULL;
this_deparse = (PlanFlatDeparse *)GetDeparseUseDeparseInfo( this_plan, flat_info );


2.4) 注意事项:
使用 hash_search这个函数进行查找的时候
返回的 entry 一定要是一个包含key的结构体!!!
例如:
typedef struct entry {
              char *key;
              void *data;
} ENTRY;
对于这个函数:
entry =  hash_search(hashp_, (void*)&node_, HASH_ENTER, found);
调用完成之后,会把key填充到entry中,然后data的部分由用户填充


2.5)  hash 函数和match函数
hash函数和match函数都是可以指定的:
hash函数末了都是调用hash_any这个函数
至于string_hash ---->  只是判断key是以\0结尾的情况
tag_hash --->  完全调用hash_any
oid_hash  -->  key是oid的情况



2.6) 注意remove的情况:
对于remove的情况:
entry =  hash_search(g_PMConnHTab, (void*)(&serveroid), HASH_REMOVE, &found);
这种情况下 entry不要手动释放, 这个由hash自己回收


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有