50 #define QMGR_LIST_ROTATE(head, object, peers) { \
51 head.next->peers.prev = head.prev; \
52 head.prev->peers.next = head.next; \
53 head.next = object->peers.next; \
54 head.next->peers.prev = 0; \
56 object->peers.next = 0; \
59 #define QMGR_LIST_UNLINK(head, type, object, peers) { \
60 type _next = object->peers.next; \
61 type _prev = object->peers.prev; \
62 if (_prev) _prev->peers.next = _next; \
63 else head.next = _next; \
64 if (_next) _next->peers.prev = _prev; \
65 else head.prev = _prev; \
66 object->peers.next = object->peers.prev = 0; \
69 #define QMGR_LIST_LINK(head, pred, object, succ, peers) { \
70 object->peers.prev = pred; \
71 object->peers.next = succ; \
72 if (pred) pred->peers.next = object; \
73 else head.next = object; \
74 if (succ) succ->peers.prev = object; \
75 else head.prev = object; \
78 #define QMGR_LIST_PREPEND(head, object, peers) { \
79 object->peers.next = head.next; \
80 object->peers.prev = 0; \
82 head.next->peers.prev = object; \
89 #define QMGR_LIST_APPEND(head, object, peers) { \
90 object->peers.prev = head.prev; \
91 object->peers.next = 0; \
93 head.prev->peers.next = object; \
100 #define QMGR_LIST_INIT(head) { \
131 #define QMGR_FEEDBACK_IDX_NONE 0
132 #define QMGR_FEEDBACK_IDX_WIN 1
134 #define QMGR_FEEDBACK_IDX_SQRT_WIN 2
137 #ifdef QMGR_FEEDBACK_IDX_SQRT_WIN
143 #ifndef QMGR_FEEDBACK_IDX_SQRT_WIN
144 #define QMGR_FEEDBACK_VAL(fb, win) \
145 ((fb).index == QMGR_FEEDBACK_IDX_NONE ? (fb).base : (fb).base / (win))
147 #define QMGR_FEEDBACK_VAL(fb, win) \
148 ((fb).index == QMGR_FEEDBACK_IDX_NONE ? (fb).base : \
149 (fb).index == QMGR_FEEDBACK_IDX_WIN ? (fb).base / (win) : \
150 (fb).base / sqrt(win))
211 #define QMGR_TRANSPORT_STAT_DEAD (1<<1)
212 #define QMGR_TRANSPORT_STAT_RATE_LOCK (1<<2)
222 #define QMGR_TRANSPORT_THROTTLED(t) ((t)->flags & QMGR_TRANSPORT_STAT_DEAD)
256 #define QMGR_QUEUE_TODO 1
257 #define QMGR_QUEUE_BUSY 2
278 #define QMGR_QUEUE_STAT_THROTTLED 0
279 #define QMGR_QUEUE_STAT_SUSPENDED -1
280 #define QMGR_QUEUE_STAT_SAVED -2
281 #define QMGR_QUEUE_STAT_BAD -3
283 #define QMGR_QUEUE_READY(q) ((q)->window > 0)
284 #define QMGR_QUEUE_THROTTLED(q) ((q)->window == QMGR_QUEUE_STAT_THROTTLED)
285 #define QMGR_QUEUE_SUSPENDED(q) ((q)->window == QMGR_QUEUE_STAT_SUSPENDED)
286 #define QMGR_QUEUE_SAVED(q) ((q)->window == QMGR_QUEUE_STAT_SAVED)
287 #define QMGR_QUEUE_BAD(q) ((q)->window <= QMGR_QUEUE_STAT_BAD)
289 #define QMGR_QUEUE_STATUS(q) ( \
290 QMGR_QUEUE_READY(q) ? "ready" : \
291 QMGR_QUEUE_THROTTLED(q) ? "throttled" : \
292 QMGR_QUEUE_SUSPENDED(q) ? "suspended" : \
293 QMGR_QUEUE_SAVED(q) ? "saved" : \
294 "invalid queue status" \
377 #define QMGR_READ_FLAG_SEEN_ALL_NON_RCPT (1<<16)
379 #define QMGR_MESSAGE_LOCKED ((QMGR_MESSAGE *) 1)
391 #define QMGR_MSG_STATS(stats, message) \
392 MSG_STATS_INIT2(stats, \
393 incoming_arrival, message->arrival_time, \
394 active_arrival, message->active_time)
483 extern void qmgr_move(
const char *,
const char *, time_t);
506 #define QMGR_SCAN_START (1<<0)
507 #define QMGR_SCAN_ALL (1<<1)
508 #define QMGR_FLUSH_ONCE (1<<2)
509 #define QMGR_FLUSH_DFXP (1<<3)
510 #define QMGR_FLUSH_EACH (1<<4)
struct HTABLE * job_byname
int qmgr_active_feed(QMGR_SCAN *, const char *)
QMGR_QUEUE * qmgr_error_queue(const char *, DSN *)
void qmgr_message_free(QMGR_MESSAGE *)
QMGR_PEER * qmgr_peer_find(QMGR_JOB *, QMGR_QUEUE *)
int dest_concurrency_limit
void qmgr_peer_free(QMGR_PEER *)
void qmgr_job_free(QMGR_JOB *)
QMGR_ENTRY * qmgr_job_entry_select(QMGR_TRANSPORT *)
void qmgr_message_kill_record(QMGR_MESSAGE *, long)
QMGR_JOB_LIST message_peers
QMGR_TRANSPORT * qmgr_transport_create(const char *)
struct timeval active_time
QMGR_TRANSPORT * qmgr_error_transport(const char *)
void qmgr_queue_suspend(QMGR_QUEUE *, int)
QMGR_FEEDBACK neg_feedback
void qmgr_entry_move_todo(QMGR_QUEUE *, QMGR_ENTRY *)
struct HTABLE * peer_byname
QMGR_QUEUE * qmgr_queue_create(QMGR_TRANSPORT *, const char *, const char *)
void qmgr_bounce_recipient(QMGR_MESSAGE *, RECIPIENT *, DSN *)
int init_dest_concurrency
void qmgr_message_update_warn(QMGR_MESSAGE *)
QMGR_SCAN * qmgr_scan_create(const char *)
void qmgr_queue_unthrottle(QMGR_QUEUE *)
QMGR_MESSAGE * qmgr_message_alloc(const char *, const char *, int, mode_t)
struct timeval arrival_time
struct HTABLE * queue_byname
QMGR_JOB * qmgr_job_obtain(QMGR_MESSAGE *, QMGR_TRANSPORT *)
QMGR_PEER * qmgr_peer_select(QMGR_JOB *)
QMGR_TRANSPORT * qmgr_transport_find(const char *)
QMGR_MESSAGE * qmgr_message_realloc(QMGR_MESSAGE *)
void qmgr_active_drain(void)
QMGR_JOB_LIST stack_siblings
void qmgr_scan_request(QMGR_SCAN *, int)
QMGR_PEER * qmgr_peer_obtain(QMGR_JOB *, QMGR_QUEUE *)
QMGR_QUEUE * qmgr_queue_find(QMGR_TRANSPORT *, const char *)
QMGR_JOB_LIST stack_children
QMGR_ENTRY * qmgr_entry_create(QMGR_QUEUE *, QMGR_MESSAGE *)
void qmgr_enable_queue(QMGR_QUEUE *)
void qmgr_queue_done(QMGR_QUEUE *)
void qmgr_job_blocker_update(QMGR_QUEUE *)
void qmgr_queue_throttle(QMGR_QUEUE *, DSN *)
void qmgr_active_done(QMGR_MESSAGE *)
void qmgr_entry_unselect(QMGR_QUEUE *, QMGR_ENTRY *)
QMGR_TRANSPORT_LIST peers
QMGR_ENTRY * qmgr_entry_select(QMGR_QUEUE *)
QMGR_JOB * job_next_unread
void qmgr_defer_transport(QMGR_TRANSPORT *, DSN *)
void qmgr_entry_done(QMGR_ENTRY *, int)
int qmgr_deliver_concurrency
QMGR_TRANSPORT * transport
QMGR_JOB * candidate_cache
void qmgr_deliver(QMGR_TRANSPORT *, VSTREAM *)
time_t candidate_cache_time
void qmgr_transport_throttle(QMGR_TRANSPORT *, DSN *)
QMGR_PEER * qmgr_peer_create(QMGR_JOB *, QMGR_QUEUE *)
void qmgr_enable_all(void)
QMGR_ENTRY_LIST queue_peers
void qmgr_defer_recipient(QMGR_MESSAGE *, RECIPIENT *, DSN *)
QMGR_TRANSPORT * transport
void qmgr_transport_unthrottle(QMGR_TRANSPORT *)
void qmgr_enable_transport(QMGR_TRANSPORT *)
void qmgr_defer_todo(QMGR_QUEUE *, DSN *)
void qmgr_transport_alloc(QMGR_TRANSPORT *, QMGR_TRANSPORT_ALLOC_NOTIFY)
QMGR_ENTRY_LIST peer_peers
QMGR_QUEUE_LIST queue_list
void qmgr_feedback_init(QMGR_FEEDBACK *, const char *, const char *, const char *, const char *)
QMGR_TRANSPORT * qmgr_transport_select(void)
char * qmgr_error_nexthop(DSN *)
QMGR_JOB * candidate_cache_current
void qmgr_move(const char *, const char *, time_t)
QMGR_FEEDBACK pos_feedback
QMGR_TRANSPORT_LIST qmgr_transport_list
struct HTABLE * qmgr_transport_byname
QMGR_ENTRY_LIST entry_list
char * qmgr_scan_next(QMGR_SCAN *)
void qmgr_job_move_limits(QMGR_JOB *)
void(* QMGR_TRANSPORT_ALLOC_NOTIFY)(QMGR_TRANSPORT *, VSTREAM *)
QMGR_JOB_LIST transport_peers