版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zg_hover/article/details/82250449
概述
本文描述了beanstalkd中peek命令的实现原理。
peek命令的说明
该命令让client在系统中检查job,若存在则返回该job结构体,否则返回NOT_FOUND。
有四种形式的命令,其中第一种形式的指令是针对当前使用的tube格式。
peek <id>\r\n 返回id对应的job
peek-ready\r\n 返回下一个ready job
peek-delayed\r\n 返回下一个延迟剩余时间最短的job
peek-buried\r\n 返回下一个在buried列表中的job
- 响应
- 响应 NOT_FOUND\r\n 如果job不存在,或者没有对应状态的job
FOUND <id> <bytes>\r\n <data>\r\n
- id 为对应的job id bytes job body的字节数 data 为job body
- 响应 NOT_FOUND\r\n 如果job不存在,或者没有对应状态的job
peek命令源码分析
peek命令分析
peek命令的实现逻辑如下:
1. 获取参数:job id。
2. 从全局job的哈希表(all_jobs)中查找该job,若找到新申请一块内存,把job的内容复制到新的内存块。
3. 给客户端返回保存job的新内存块的地址中的内容。
4. 把新保存job内存块的地址赋值给,连接的c->out_job变量,该内存块会在发送完成后被释放。
为什么要新申请一块内存?主要防止job正在被删除的情况。
peek命令源码
case OP_PEEKJOB:
errno = 0;
// 获取参数:job id
id = strtoull(c->cmd + CMD_PEEKJOB_LEN, &end_buf, 10);
if (errno) return reply_msg(c, MSG_BAD_FORMAT);
op_ct[type]++;
// 把找到的job复制到新的内存,防止在peek的job,正在被删除
/* So, peek is annoying, because some other connection might free the
* job while we are still trying to write it out. So we copy it and
* then free the copy when it's done sending. */
j = job_copy(peek_job(id));
if (!j) return reply(c, MSG_NOTFOUND, MSG_NOTFOUND_LEN, STATE_SENDWORD);
reply_job(c, j, MSG_FOUND);
break;
peek-ready命令的实现
该命令返回下一个ready的job。该命令的实现逻辑如下:
1. 从当前使用tube的ready堆中,复制堆顶元素,并返回
注意:这里是复制,并没有从对中删除元素。
...
if (c->use->ready.len) {
j = job_copy(c->use->ready.data[0]);
}
...
peek-delay命令的实现
该命令从当前使用tube的delay堆中,复制堆顶元素,并返回。
注意:同上一个命令一样,都是复制,不会把元素取出来。这里的堆顶元素意味着:该job的延迟时间是最小的。
...
if (c->use->delay.len) {
j = job_copy(c->use->delay.data[0]);
}
...
peek-buried命令的实现
该命令从当前连接的buried链表中,复制一个job,并返回。若该链表为空,返回NULL。
...
j = job_copy(buried_job_p(c->use)? j = c->use->buried.next : NULL);
...
总结
本文讲述了各种peek命令的实现原理,可见peek命令是一个检查命令,不会对各种队列的job做实质性的删除,转移的工作。他会复制一份job的内存空间,返回的是新分配的内存空间的job实体内容。