summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/scheduler_ramqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/smtpd/scheduler_ramqueue.c')
-rw-r--r--usr.sbin/smtpd/scheduler_ramqueue.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/usr.sbin/smtpd/scheduler_ramqueue.c b/usr.sbin/smtpd/scheduler_ramqueue.c
index 2578606810e..7703c0fea66 100644
--- a/usr.sbin/smtpd/scheduler_ramqueue.c
+++ b/usr.sbin/smtpd/scheduler_ramqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_ramqueue.c,v 1.34 2013/12/03 10:38:40 eric Exp $ */
+/* $OpenBSD: scheduler_ramqueue.c,v 1.35 2013/12/05 09:26:47 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -60,8 +60,10 @@ struct rq_envelope {
#define RQ_ENVELOPE_EXPIRED 0x01
#define RQ_ENVELOPE_REMOVED 0x02
#define RQ_ENVELOPE_SUSPEND 0x04
+#define RQ_ENVELOPE_UPDATE 0x08
uint8_t flags;
+ time_t ctime;
time_t sched;
time_t expire;
@@ -86,6 +88,7 @@ struct rq_queue {
struct evplist q_mta;
struct evplist q_mda;
struct evplist q_bounce;
+ struct evplist q_update;
struct evplist q_expired;
struct evplist q_removed;
};
@@ -197,6 +200,7 @@ scheduler_ram_insert(struct scheduler_info *si)
envelope->evpid = si->evpid;
envelope->type = si->type;
envelope->message = message;
+ envelope->ctime = si->creation;
envelope->expire = si->creation + si->expire;
envelope->sched = scheduler_compute_schedule(si);
tree_xset(&message->envelopes, envelope->evpid, envelope);
@@ -381,7 +385,7 @@ scheduler_ram_release(int type, uint64_t holdq, int n)
{
struct rq_holdq *hq;
struct rq_envelope *evp;
- int i;
+ int i, update;
currtime = time(NULL);
@@ -389,6 +393,13 @@ scheduler_ram_release(int type, uint64_t holdq, int n)
if (hq == NULL)
return (0);
+ if (n == -1) {
+ n = 0;
+ update = 1;
+ }
+ else
+ update = 0;
+
for (i = 0; n == 0 || i < n; i++) {
evp = TAILQ_FIRST(&hq->q);
if (evp == NULL)
@@ -402,6 +413,8 @@ scheduler_ram_release(int type, uint64_t holdq, int n)
* we could just schedule them directly.
*/
evp->state = RQ_EVPSTATE_PENDING;
+ if (update)
+ evp->flags |= RQ_ENVELOPE_UPDATE;
sorted_insert(&ramqueue, evp);
}
@@ -420,6 +433,7 @@ scheduler_ram_batch(int typemask, struct scheduler_batch *ret)
struct evplist *q;
struct rq_envelope *evp;
size_t n;
+ int retry;
currtime = time(NULL);
@@ -435,6 +449,10 @@ scheduler_ram_batch(int typemask, struct scheduler_batch *ret)
q = &ramqueue.q_expired;
ret->type = SCHED_EXPIRE;
}
+ else if (typemask & SCHED_UPDATE && TAILQ_FIRST(&ramqueue.q_update)) {
+ q = &ramqueue.q_update;
+ ret->type = SCHED_UPDATE;
+ }
else if (typemask & SCHED_BOUNCE && TAILQ_FIRST(&ramqueue.q_bounce)) {
q = &ramqueue.q_bounce;
ret->type = SCHED_BOUNCE;
@@ -474,6 +492,19 @@ scheduler_ram_batch(int typemask, struct scheduler_batch *ret)
if (ret->type == SCHED_REMOVE || ret->type == SCHED_EXPIRE)
rq_envelope_delete(&ramqueue, evp);
+ else if (ret->type == SCHED_UPDATE) {
+
+ evp->flags &= ~RQ_ENVELOPE_UPDATE;
+
+ /* XXX we can't really use scheduler_compute_schedule */
+ retry = 0;
+ while ((evp->sched = evp->ctime + 800 * retry * retry / 2) <= currtime)
+ retry += 1;
+
+ evp->state = RQ_EVPSTATE_PENDING;
+ if (!(evp->flags & RQ_ENVELOPE_SUSPEND))
+ sorted_insert(&ramqueue, evp);
+ }
else {
TAILQ_INSERT_TAIL(&ramqueue.q_inflight, evp, entry);
evp->state = RQ_EVPSTATE_INFLIGHT;
@@ -717,6 +748,7 @@ rq_queue_init(struct rq_queue *rq)
TAILQ_INIT(&rq->q_mta);
TAILQ_INIT(&rq->q_mda);
TAILQ_INIT(&rq->q_bounce);
+ TAILQ_INIT(&rq->q_update);
TAILQ_INIT(&rq->q_expired);
TAILQ_INIT(&rq->q_removed);
SPLAY_INIT(&rq->q_priotree);
@@ -793,6 +825,8 @@ rq_envelope_list(struct rq_queue *rq, struct rq_envelope *evp)
return &rq->q_expired;
if (evp->flags & RQ_ENVELOPE_REMOVED)
return &rq->q_removed;
+ if (evp->flags & RQ_ENVELOPE_UPDATE)
+ return &rq->q_update;
if (evp->type == D_MTA)
return &rq->q_mta;
if (evp->type == D_MDA)
@@ -830,6 +864,9 @@ rq_envelope_schedule(struct rq_queue *rq, struct rq_envelope *evp)
break;
}
+ if (evp->flags & RQ_ENVELOPE_UPDATE)
+ q = &rq->q_update;
+
if (evp->state == RQ_EVPSTATE_HELD) {
hq = tree_xget(&holdqs[evp->type], evp->holdq);
TAILQ_REMOVE(&hq->q, evp, entry);