80 static void qmgr_job_pop(
QMGR_JOB *);
84 #define HAS_ENTRIES(job) ((job)->selected_entries < (job)->read_entries)
91 #define MIN_ENTRIES(job) ((job)->read_entries)
92 #define MAX_ENTRIES(job) ((job)->read_entries + (job)->message->rcpt_unread)
94 #define RESET_CANDIDATE_CACHE(transport) ((transport)->candidate_cache_current = 0)
96 #define IS_BLOCKER(job,transport) ((job)->blocker_tag == (transport)->blocker_tag)
129 static void qmgr_job_link(
QMGR_JOB *job)
133 QMGR_JOB *prev, *next, *list_prev, *list_next, *unread, *current;
255 if ((job = qmgr_job_find(message, transport)) == 0)
256 job = qmgr_job_create(message, transport);
283 int rcpt_unused, msg_rcpt_unused;
302 if (msg_rcpt_unused < rcpt_unused)
303 rcpt_unused = msg_rcpt_unused;
311 if (rcpt_unused > 0) {
315 if (next != 0 && (rcpt_unused = transport->
rcpt_unused) > 0) {
339 static void qmgr_job_unlink(
QMGR_JOB *job)
341 const char *myname =
"qmgr_job_unlink";
352 msg_panic(
"%s: siblings present", myname);
358 qmgr_job_parent_gone(job, 0);
383 static void qmgr_job_retire(
QMGR_JOB *job)
407 qmgr_job_unlink(job);
414 const char *myname =
"qmgr_job_free";
445 qmgr_job_unlink(job);
454 static void qmgr_job_count_slots(
QMGR_JOB *job)
488 double score, best_score = 0.0;
489 int max_slots, max_needed_entries, max_total_entries;
544 if (max_needed_entries > 0 && max_needed_entries <= max_slots) {
545 score = (double) delay / max_total_entries;
546 if (score > best_score) {
555 if (delay <= best_score && job->stack_level == 0)
574 const char *myname =
"qmgr_job_preempt";
598 if ((job = qmgr_job_candidate(current)) == 0)
605 msg_panic(
"%s: attempt to preempt itself", myname);
688 static void qmgr_job_pop(
QMGR_JOB *job)
690 const char *myname =
"qmgr_job_pop";
735 qmgr_job_parent_gone(job, parent);
848 job = qmgr_job_preempt(job);
865 for ( ; job; job = next) {
875 if ((peer = qmgr_job_peer_select(job)) != 0) {
882 qmgr_job_count_slots(job);
908 qmgr_job_retire(job);
934 qmgr_job_retire(job);
struct HTABLE * job_byname
void htable_free(HTABLE *table, void(*free_fn)(void *))
QMGR_JOB * qmgr_job_obtain(QMGR_MESSAGE *message, QMGR_TRANSPORT *transport)
NORETURN msg_panic(const char *fmt,...)
void qmgr_job_free(QMGR_JOB *job)
struct HTABLE * peer_byname
#define QMGR_LIST_INIT(head)
#define QMGR_LIST_APPEND(head, object)
HTABLE * htable_create(ssize_t size)
QMGR_PEER * qmgr_peer_select(QMGR_JOB *)
QMGR_MESSAGE * qmgr_message_realloc(QMGR_MESSAGE *)
QMGR_JOB_LIST stack_siblings
QMGR_JOB_LIST stack_children
QMGR_ENTRY * qmgr_entry_select(QMGR_QUEUE *)
QMGR_JOB * job_next_unread
void * htable_find(HTABLE *table, const char *key)
#define IS_BLOCKER(job, transport)
#define RESET_CANDIDATE_CACHE(transport)
QMGR_TRANSPORT * transport
QMGR_JOB * candidate_cache
time_t candidate_cache_time
QMGR_TRANSPORT * transport
void qmgr_job_blocker_update(QMGR_QUEUE *queue)
#define QMGR_LIST_UNLINK(head, type, object)
#define QMGR_LIST_LINK(head, pred, object, succ, peers)
QMGR_JOB * candidate_cache_current
void htable_delete(HTABLE *table, const char *key, void(*free_fn)(void *))
QMGR_ENTRY * qmgr_job_entry_select(QMGR_TRANSPORT *transport)
QMGR_ENTRY_LIST entry_list
#define QMGR_QUEUE_THROTTLED(q)
void qmgr_job_move_limits(QMGR_JOB *job)
QMGR_JOB_LIST transport_peers
void * mymalloc(ssize_t len)
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
void msg_info(const char *fmt,...)