skynet底层源码阅读(4)-服务管理

来源:互联网 发布:淘宝千里眼软件怎么样 编辑:程序博客网 时间:2024/05/22 17:07

 在分析skynet的核心的服务代码之前,首先分析一下skynet对多个服务的管理。在Skynet_handle.c中,有:

//实质就是管理一个 skynet_context 的指针数组 ,还有一个handle_name数组struct handle_storage {//读写锁struct rwlock lock;//服务所属 harbor harbor 用于不同主机间通信 uint32_t harbor;//初始值为1,表示handler句柄起始值从1开始uint32_t handle_index;//slot数组的大小 int slot_size;//指针数组,保存skynet_context指针struct skynet_context ** slot;//skynet_context 表空间//handler_name容量,初始为2,这里name_cap与slot_size不一样的原因在于,不是每一个handler都有nameint name_cap;int name_count;//handler_name数量//存放handle_name的数组struct handle_name *name;//handler_name表 数组};//创建全局变量static struct handle_storage *H = NULL;

//handle_name 服务 和对应 handle id的hash表struct handle_name {char * name;//handle是一个uint32_t的整数,高八位表示远程节点(这是框架自带的集群设施,后面的分析都会无视该部分// 一来,他不是框架的核心,二来这个集群设施已经不被推荐使用)uint32_t handle;};
简单的说,就是管理了服务结构体指针数组,还有服务对应的名字。skynet中用户可以给服务命名,服务在数组中的位置就是服务的id;之后就是对该容器的操作了,并不复杂

加入服务:

//实质就是将ctx存入到handle_storage维护的一个指针数组中uint32_tskynet_handle_register(struct skynet_context  *ctx) {struct handle_storage *s = H;//加写锁rwlock_wlock(&s->lock);for (;;) {int i;//hash选值for (i=0;i<s->slot_size;i++) {//handle是一个uint32_t的整数,高八位表示远程节点(这是框架自带的集群设施,后面的分析都会无视该部分             //#define HANDLE_MASK 0xffffff   就是 00000000 11111111 11111111 11111111             //x&HANDLE_MASK 是将x的高八位变成0uint32_t handle = (i+s->handle_index) & HANDLE_MASK; //等价于handler % s->slot_sizeint hash = handle & (s->slot_size-1);if (s->slot[hash] == NULL) {//找到未使用的 slot 将这个ctx放入到这个slot中 s->slot[hash] = ctx;s->handle_index = handle + 1;//移动 handler_index 方便下次使用rwlock_wunlock(&s->lock);//harbor 用于不同主机之间的通信,handler高8位用于harbor 低24为用于本机的//所以这里要 |=一下handle |= s->harbor;return handle;}}//运行到这里,说明数组满了,//确保扩大 2倍空间之后 总共handler即 slot的数量不超过 24位限制assert((s->slot_size*2 - 1) <= HANDLE_MASK);//哈希表扩大两倍struct skynet_context ** new_slot = skynet_malloc(s->slot_size * 2 * sizeof(struct skynet_context *));memset(new_slot, 0, s->slot_size * 2 * sizeof(struct skynet_context *));//将原来的数据拷贝到新空间for (i=0;i<s->slot_size;i++) {//映射新的hash值int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1);assert(new_slot[hash] == NULL);new_slot[hash] = s->slot[i];}//销毁原来的指针数组skynet_free(s->slot);s->slot = new_slot;s->slot_size *= 2;}}

//根据名称查找handleuint32_t skynet_handle_findname(const char * name) {struct handle_storage *s = H;rwlock_rlock(&s->lock);uint32_t handle = 0;int begin = 0;int end = s->name_count - 1;//这里使用二分查找,听说会有整数溢出,。。。。while (begin<=end) {int mid = (begin+end)/2;struct handle_name *n = &s->name[mid];int c = strcmp(n->name, name);//一直在头部插入,实际这样插入后name会按长度大小排序,这样就能使用二分查找了if (c==0) {handle = n->handle;break;}if (c<0) {begin = mid + 1;} else {end = mid - 1;}}rwlock_runlock(&s->lock);return handle;}



原创粉丝点击