6.9.1.1 qmgr_defer_todo:为延迟邮件清理待发送收件人列表
2016-04-07 15:32
253 查看
/qmgr/qmgr_ defer.c 106 /* qmgr_defer_todo - defer all todoqueue entries for specific site */ 107 108 void qmgr_defer_todo(QMGR_QUEUE *queue, DSN *dsn) 109 { 110 QMGR_ENTRY *entry; 111 QMGR_ENTRY *next; 112 QMGR_MESSAGE *message; 113 RECIPIENT *recipient; 114 int nrcpt; 115 QMGR_QUEUE *retry_queue; 116 117 /* 118 * Sanity checks. 119 */ 120 if (msg_verbose) 121 msg_info("defer site %s: %s %s", 122 queue->name,dsn->status, dsn->reason); 123 124 /* 125 * See if we can redirect the deliveries to the retry(8) delivery agent, 126 * so that they can be handled asynchronously. If the retry(8) service is 127 * unavailable, use the synchronous defer(8) server. With a large todo 128 * queue, this blocks the queue manager for a significant time. 129 */ 130 retry_queue = qmgr_error_queue(MAIL_SERVICE_RETRY, dsn);
130 qmgr_defer_todo优先使用retry MDA处理暂时无法发送的QMGR_ENTRY。对于retry MDA,将为每一种遇到的DSN错误建立一个QMGR_QUEUE。
qmgr_error_queue函数查找或创建retryMDA:
/* * Find or create transport. */ if ((transport = qmgr_error_transport(service)) == 0) return(0);
为每一种DSN错误类型建立一个QMGR_QUEEN:
/* * Find or create queue. */ nexthop = qmgr_error_nexthop(dsn); if ((queue = qmgr_queue_find(transport, nexthop)) == 0) queue= qmgr_queue_create(transport, nexthop, nexthop);
QMGR_QUEUE的名字根据DSN错误信息来构造:
/* qmgr_error_nexthop - computenext-hop information from problem description */ char *qmgr_error_nexthop(DSN *dsn) { char *nexthop; nexthop = concatenate(dsn->status, " ", dsn->reason,(char *) 0); return (nexthop); }
qmgr_defer_todo会在qmgr_defer_transport或qmgr_deliver_update中被调用,分别代表两种错误:
4.3.0,错误信息为"mailtransport unavailable"
4.0.0,错误信息为”unknow error”
131 132 /* 133 * Proceed carefully. Queue entries may disappear as a side effect. 134 */ 135 for (entry = queue->todo.next; entry != 0; entry = next) { 136 next = entry->queue_peers.next; 137 if (retry_queue != 0) { 138 qmgr_entry_move_todo(retry_queue,entry); 139 continue; 140 } 141 message = entry->message; 142 for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) { 143 recipient =entry->rcpt_list.info + nrcpt; 144 qmgr_defer_recipient(message,recipient, dsn); 145 } 146 qmgr_entry_done(entry, QMGR_QUEUE_TODO); 147 }
135-147 循环该QMGR_QUEUE的todo QMGR_ENTRY_LIST,延迟发信。
这里对延迟分两种情况处理:存在retry MDA或不存在retry MDA的情况。这样的区分支持异步方式处理。
如果存在error模块,则使用qmgr_entry_move_todo函数将原QMGR_QUEUE的todo QMGR_ENTRY_LIST移动到retry MDA的以DSN错误代码为名称的QMGR_QUEUE的todo QMGR_ENTRY_LIST:
/* * Create new entry, swap the recipients between the two entries, * adjusting the job counters accordingly, then dispose of the old entry. * * Note that qmgr_entry_done() will also take care of adjusting the * recipient limits of all the message jobs, so we do not have to do that * explicitly for the new job here. * * XXX This does not enforce the per-entry recipient limit, but that isnot * a problem as long as qmgr_entry_move_todo() is called only to bounce * or defer mail. */ dst_job = qmgr_job_obtain(message, dst_transport); dst_peer = qmgr_peer_obtain(dst_job, dst_queue); new_entry = qmgr_entry_create(dst_peer, message); recipient_list_swap(&entry->rcpt_list,&new_entry->rcpt_list);
如果无法找到或建立retryQMGR_QUEUE,则调用qmgr_defer_recipient。qmgr_defer_recipient-> defer_append->defer_append_intern将直接联系bounce模块完成延迟处理工作。
148 } 149 150 /* qmgr_defer_recipient - deferdelivery of specific recipient */ 151 152 void qmgr_defer_recipient(QMGR_MESSAGE *message, RECIPIENT *recipient, 153 DSN *dsn) 154 { 155 MSG_STATS stats; 156 157 /* 158 * Update the message structure and log the message disposition. 159 */ 160 message->flags |= defer_append(message->tflags,message->queue_id, 161 QMGR_MSG_STATS(&stats, message),recipient, 162 "none", dsn); 163 }
无论是否存在retry MDA,最终都会调用qmgr_entry_done函数,该函数最终销毁无法使用的QMGR_ENTRY结构体。如果存在retry MDA,虽然continue语句会跳出本次循环,但qmgr_entry_move_todo函数中会调用qmgr_entry_done函数。如果不存在retry MDA,则会执行qmgr_entry_done函数,该函数的第二个参数接收
#define QMGR_QUEUE_TODO 1 /* waiting for service */
#define QMGR_QUEUE_BUSY 2 /*recipients on the wire */
这两个选项,对于延迟发信,均使用选项QMGR_QUEUE_TODO。
相关文章推荐
- 6.9.1 qmgr_ defer.c:销毁活动数据
- CSS 制作三角形原理剖析
- css选择器总结
- 多层json解析
- hadoop SecondNamenode
- (OK) VirtualBox 5.0.10 中 Fedora 23 在安装了增强工具后无法自动调节虚拟机分辨率的问题
- 剑指Offer——翻转英文句子中的单词顺序
- javascript 之闭包详解
- react-native-闪屏页
- 剑指offer:二叉树的下一个结点
- 理解 Javascript 的闭包
- 样式设置
- 【剑指offer系列】 打印1到最大的n位数___12
- javascript闭包详解
- php的date对象与javascript的Date对象区别
- 通过原生js添加div和css
- AngularJs 过滤器
- 制作单页的动画插件
- ReactNative学习十三-Props和State
- js正则验证之不能使用相同字符