<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -689,6 +689,24 @@ h_conn(const int fd, const short which, conn c)
 }
 
 static void
+h_delay()
+{
+    int r;
+    job j;
+    time_t t;
+
+    t = time(NULL);
+    while ((j = delay_q_peek())) {
+        if (j-&gt;deadline &gt; t) break;
+        j = delay_q_take();
+        r = enqueue_job(j, 0);
+        if (!r) bury_job(j); /* there was no room in the queue, so bury it */
+    }
+
+    set_main_timeout((j = delay_q_peek()) ? j-&gt;deadline : 0);
+}
+
+static void
 h_accept(const int fd, const short which, struct event *ev)
 {
     conn c;
@@ -696,6 +714,8 @@ h_accept(const int fd, const short which, struct event *ev)
     socklen_t addrlen;
     struct sockaddr addr;
 
+    if (which == EV_TIMEOUT) return h_delay();
+
     addrlen = sizeof addr;
     cfd = accept(fd, &amp;addr, &amp;addrlen);
     if (cfd == -1) {</diff>
      <filename>beanstalkd.c</filename>
    </modified>
    <modified>
      <diff>@@ -55,13 +55,13 @@ job_pri_cmp(job a, job b)
 int
 job_delay_cmp(job a, job b)
 {
-    if (a-&gt;delay == b-&gt;delay) {
+    if (a-&gt;deadline == b-&gt;deadline) {
         /* we can't just subtract because id has too many bits */
         if (a-&gt;id &gt; b-&gt;id) return 1;
         if (a-&gt;id &lt; b-&gt;id) return -1;
         return 0;
     }
-    return a-&gt;delay - b-&gt;delay;
+    return a-&gt;deadline - b-&gt;deadline;
 }
 
 job</diff>
      <filename>job.c</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,8 @@
 static int listen_socket = -1;
 static struct event listen_evq;
 static evh accept_handler;
+static time_t main_deadline = 0;
+static int brakes_are_on = 1;
 
 int
 make_server_socket(int host, int port)
@@ -51,6 +53,8 @@ brake()
 {
     int r;
 
+    if (brakes_are_on) return;
+    brakes_are_on = 1;
     twarnx(&quot;too many connections; putting on the brakes&quot;);
 
     r = event_del(&amp;listen_evq);
@@ -65,17 +69,27 @@ unbrake(evh h)
 {
     int r;
 
+    if (!brakes_are_on) return;
+    brakes_are_on = 0;
     twarnx(&quot;releasing the brakes&quot;);
 
     accept_handler = h ? : accept_handler;
     event_set(&amp;listen_evq, listen_socket, EV_READ | EV_PERSIST,
               accept_handler, &amp;listen_evq);
 
-    errno = 0;
-    r = event_add(&amp;listen_evq, NULL);
-    if (r == -1) twarn(&quot;event_add()&quot;);
+    set_main_timeout(main_deadline);
 
     r = listen(listen_socket, 1024);
     if (r == -1) twarn(&quot;listen()&quot;);
 }
 
+void
+set_main_timeout(time_t deadline)
+{
+    int r;
+    struct timeval tv = {deadline - time(NULL), 0};
+
+    main_deadline = deadline;
+    r = event_add(&amp;listen_evq, deadline ? &amp;tv : NULL);
+    if (r == -1) twarn(&quot;event_add()&quot;);
+}</diff>
      <filename>net.c</filename>
    </modified>
    <modified>
      <diff>@@ -15,5 +15,6 @@ int make_server_socket(int host, int port);
 
 void brake();
 void unbrake(evh h);
+void set_main_timeout(time_t deadline);
 
 #endif /*net_h*/</diff>
      <filename>net.h</filename>
    </modified>
    <modified>
      <diff>@@ -104,6 +104,13 @@ pq_take(pq q)
 }
 
 job
+pq_peek(pq q)
+{
+    if (q-&gt;used == 0) return NULL;
+    return q-&gt;heap[0];
+}
+
+job
 pq_find(pq q, unsigned long long int id)
 {
     unsigned int i;</diff>
      <filename>pq.c</filename>
    </modified>
    <modified>
      <diff>@@ -21,6 +21,9 @@ int pq_give(pq q, job j);
 /* return a job if the queue contains jobs, else NULL */
 job pq_take(pq q);
 
+/* return a job if the queue contains jobs, else NULL */
+job pq_peek(pq q);
+
 /* return a job that matches the given id, else NULL */
 /* This is O(n), so don't do it much. */
 job pq_find(pq q, unsigned long long int id);</diff>
      <filename>pq.h</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,7 @@
 #include &quot;conn.h&quot;
 #include &quot;util.h&quot;
 #include &quot;reserve.h&quot;
+#include &quot;net.h&quot;
 
 static pq ready_q;
 static pq delay_q;
@@ -90,9 +91,11 @@ enqueue_job(job j, unsigned int delay)
     int r;
 
     if (delay) {
+        j-&gt;deadline = time(NULL) + delay;
         r = pq_give(delay_q, j);
         if (!r) return 0;
         j-&gt;state = JOB_STATE_DELAY;
+        set_main_timeout(pq_peek(delay_q)-&gt;deadline);
     } else {
         r = pq_give(ready_q, j);
         if (!r) return 0;
@@ -103,6 +106,18 @@ enqueue_job(job j, unsigned int delay)
     return 1;
 }
 
+job
+delay_q_peek()
+{
+    return pq_peek(delay_q);
+}
+
+job
+delay_q_take()
+{
+    return pq_take(delay_q);
+}
+
 void
 bury_job(job j)
 {
@@ -157,6 +172,7 @@ job
 peek_job(unsigned long long int id)
 {
     return pq_find(ready_q, id) ? :
+           pq_find(delay_q, id) ? :
            find_reserved_job(id) ? :
            find_reserved_job_in_list(&amp;wait_queue, id) ? :
            find_buried_job(id);</diff>
      <filename>prot.c</filename>
    </modified>
    <modified>
      <diff>@@ -25,6 +25,8 @@ conn remove_waiting_conn(conn c);
 void enqueue_waiting_conn(conn c);
 
 int enqueue_job(job j, unsigned int delay);
+job delay_q_peek();
+job delay_q_take();
 void bury_job(job j);
 int kick_job();
 void process_queue();</diff>
      <filename>prot.h</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2ae48bcb7edc6245ef564a7531630df0c60145e7</id>
    </parent>
  </parents>
  <author>
    <name>Keith Rarick</name>
    <email>kr@essembly.com</email>
  </author>
  <url>http://github.com/kr/beanstalkd/commit/024fe3c1c0611bd66c52680f5ea9908675478247</url>
  <id>024fe3c1c0611bd66c52680f5ea9908675478247</id>
  <committed-date>2007-11-07T22:43:21-08:00</committed-date>
  <authored-date>2007-11-07T22:43:21-08:00</authored-date>
  <message>Finish #852 - add a delay feature.</message>
  <tree>6a7c49708f50ee1ebd120dadba7c2ffb4aba4214</tree>
  <committer>
    <name>Keith Rarick</name>
    <email>kr@essembly.com</email>
  </committer>
</commit>
