<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -255,6 +255,7 @@ main(int argc, char **argv)
 {
     int r;
     struct event_base *ev_base;
+    struct job binlog_jobs = {};
 
     progname = argv[0];
     opts(argc, argv);
@@ -278,8 +279,11 @@ main(int argc, char **argv)
     nudge_fd_limit();
 
     unbrake((evh) h_accept);
-    prot_replay_binlog();
+
+    binlog_jobs.prev = binlog_jobs.next = &amp;binlog_jobs;
+    binlog_read(&amp;binlog_jobs);
     binlog_init();
+    prot_replay_binlog(&amp;binlog_jobs);
 
     if (detach) {
         daemonize();</diff>
      <filename>beanstalkd.c</filename>
    </modified>
    <modified>
      <diff>@@ -40,12 +40,14 @@ size_t binlog_size_limit = 10 &lt;&lt; 20;
 
 char *binlog_dir = NULL;
 static int binlog_index = 0;
-static int binlog_fd = -1;
-static int binlog_version = 1;
+static int binlog_fd = -1, next_binlog_fd = -1;
+static int binlog_version = 2;
+static size_t binlog_space = 0, next_binlog_space = 0;
+static size_t binlog_reserved = 0, next_binlog_reserved = 0;
 static size_t bytes_written;
 static int lock_fd;
 
-static binlog first_binlog = NULL, last_binlog = NULL;
+static binlog first_binlog = NULL, last_binlog = NULL, next_binlog = NULL;
 
 static int
 binlog_scan_dir()
@@ -110,12 +112,19 @@ binlog_dref(binlog b)
     }
 }
 
+/*
 static void
-binlog_warn(const char *msg, int fd, const char* path)
+binlog_warn(int fd, const char* path, const char *msg)
 {
     warnx(&quot;WARNING, %s at %s:%u.\n%s&quot;, msg, path, lseek(fd, 0, SEEK_CUR),
-          &quot;  Continuing with next file. You may be missing data.&quot;);
+          &quot;  Continuing. You may be missing data.&quot;);
 }
+*/
+
+#define binlog_warn(fd, path, fmt, args...) \
+    warnx(&quot;WARNING, &quot; fmt &quot; at %s:%u. %s: &quot;, \
+          ##args, path, lseek(fd, 0, SEEK_CUR), \
+          &quot;Continuing. You may be missing data.&quot;)
 
 static void
 binlog_read_one(int fd, job binlog_jobs, const char *path)
@@ -131,7 +140,7 @@ binlog_read_one(int fd, job binlog_jobs, const char *path)
     r = read(fd, &amp;version, sizeof(version));
     if (r == -1) return twarn(&quot;read()&quot;);
     if (r &lt; sizeof(version)) {
-        return binlog_warn(&quot;version record is too short&quot;, fd, path);
+        return binlog_warn(fd, path, &quot;EOF while reading version record&quot;);
     }
 
     if (version != binlog_version) {
@@ -145,7 +154,7 @@ binlog_read_one(int fd, job binlog_jobs, const char *path)
             if (r == -1) return twarn(&quot;read()&quot;);
             if (r &lt; namelen) {
                 lseek(fd, SEEK_CUR, 0);
-                return binlog_warn(&quot;tube name is too short&quot;, fd, path);
+                return binlog_warn(fd, path, &quot;EOF while reading tube name&quot;);
             }
         }
 
@@ -153,9 +162,11 @@ binlog_read_one(int fd, job binlog_jobs, const char *path)
         r = read(fd, &amp;js, sizeof(struct job));
         if (r == -1) return twarn(&quot;read()&quot;);
         if (r &lt; sizeof(struct job)) {
-          return binlog_warn(&quot;job record is too short&quot;, fd, path);
+          return binlog_warn(fd, path, &quot;EOF while reading job record&quot;);
         }
 
+        if (!js.id) break;
+
         j = job_find(js.id);
         switch (js.state) {
         case JOB_STATE_INVALID:
@@ -175,6 +186,16 @@ binlog_read_one(int fd, job binlog_jobs, const char *path)
                 j-&gt;next = j-&gt;prev = j;
                 j-&gt;creation = js.creation;
                 job_insert(binlog_jobs, j);
+            }
+            if (js.body_size) {
+                if (js.body_size &gt; j-&gt;body_size) {
+                    warnx(&quot;job size increased from %zu to %zu&quot;, j-&gt;body_size,
+                          js.body_size);
+                    job_remove(j);
+                    binlog_dref(j-&gt;binlog);
+                    job_free(j);
+                    return binlog_warn(fd, path, &quot;EOF while reading job body&quot;);
+                }
                 r = read(fd, j-&gt;body, js.body_size);
                 if (r == -1) return twarn(&quot;read()&quot;);
                 if (r &lt; js.body_size) {
@@ -182,7 +203,7 @@ binlog_read_one(int fd, job binlog_jobs, const char *path)
                     job_remove(j);
                     binlog_dref(j-&gt;binlog);
                     job_free(j);
-                    return binlog_warn(&quot;job body is too short&quot;, fd, path);
+                    return binlog_warn(fd, path, &quot;EOF while reading job body&quot;);
                 }
             }
             break;
@@ -207,8 +228,8 @@ binlog_read_one(int fd, job binlog_jobs, const char *path)
     }
 }
 
-void
-binlog_close()
+static void
+binlog_close_last()
 {
     if (binlog_fd &lt; 0) return;
     close(binlog_fd);
@@ -217,15 +238,35 @@ binlog_close()
 }
 
 static binlog
-add_binlog(char *path)
+make_binlog(char *path)
 {
     binlog b;
 
-    b = (binlog)malloc(sizeof(struct binlog) + strlen(path) + 1);
+    b = (binlog) malloc(sizeof(struct binlog) + strlen(path) + 1);
     if (!b) return twarnx(&quot;OOM&quot;), NULL;
     strcpy(b-&gt;path, path);
     b-&gt;refs = 0;
     b-&gt;next = NULL;
+    return b;
+}
+
+static binlog
+make_next_binlog()
+{
+    int r;
+    char path[PATH_MAX];
+
+    if (!binlog_dir) return NULL;
+
+    r = snprintf(path, PATH_MAX, &quot;%s/binlog.%d&quot;, binlog_dir, ++binlog_index);
+    if (r &gt; PATH_MAX) return twarnx(&quot;path too long: %s&quot;, binlog_dir), NULL;
+
+    return make_binlog(path);
+}
+
+static binlog
+add_binlog(binlog b)
+{
     if (last_binlog) last_binlog-&gt;next = b;
     last_binlog = b;
     if (!first_binlog) first_binlog = b;
@@ -234,59 +275,82 @@ add_binlog(char *path)
 }
 
 static int
-binlog_open()
+binlog_open(binlog log)
 {
-    char path[PATH_MAX];
-    binlog b;
     int fd, r;
 
-    if (!binlog_dir) return -1;
-    r = snprintf(path, PATH_MAX, &quot;%s/binlog.%d&quot;, binlog_dir, ++binlog_index);
-    if (r &gt; PATH_MAX) return twarnx(&quot;path too long: %s&quot;, binlog_dir), -1;
+    if (!binlog_iref(log)) return -1;
 
-    if (!binlog_iref(add_binlog(path))) return -1;
-    fd = open(path, O_WRONLY | O_CREAT, 0400);
+    fd = open(log-&gt;path, O_WRONLY | O_CREAT, 0400);
 
-    if (fd &lt; 0) {
-        twarn(&quot;Cannot open binlog %s&quot;, path);
-        return -1;
-    }
+    if (fd &lt; 0) return twarn(&quot;Cannot open binlog %s&quot;, log-&gt;path), -1;
 
+    r = posix_fallocate(fd, 0, binlog_size_limit);
+    if (r) {
+        close(fd);
+        binlog_dref(log);
+        errno = r;
+        return twarn(&quot;Cannot allocate space for binlog %s&quot;, log-&gt;path), -1;
+    }
 
     bytes_written = write(fd, &amp;binlog_version, sizeof(int));
 
     if (bytes_written &lt; sizeof(int)) {
         twarn(&quot;Cannot write to binlog&quot;);
         close(fd);
-        binlog_dref(last_binlog);
+        binlog_dref(log);
         return -1;
     }
 
     return fd;
 }
 
-static void
-binlog_open_next()
+/* returns 1 on success, 0 on error. */
+static int
+binlog_use_next()
 {
-    if (binlog_fd &lt; 0) return;
-    close(binlog_fd);
-    binlog_dref(last_binlog);
-    binlog_fd = binlog_open();
+    if (binlog_fd &lt; 0) return 0;
+    if (next_binlog_fd &lt; 0) return 0;
+    if (binlog_reserved &gt; next_binlog_space) return twarnx(&quot;overextended&quot;), 0;
+
+    binlog_close_last();
+
+    binlog_fd = next_binlog_fd;
+    add_binlog(next_binlog);
+
+    next_binlog = NULL;
+    next_binlog_fd = -1;
+
+    binlog_space = next_binlog_space - binlog_reserved;
+    binlog_reserved = next_binlog_reserved + binlog_reserved;
+
+    next_binlog_reserved = next_binlog_space = 0;
+    return 1;
 }
 
 void
+binlog_close()
+{
+    binlog_use_next();
+    binlog_close_last();
+}
+
+/* Returns the number of jobs successfully written (either 0 or 1). */
+/* If we are not using the binlog at all (binlog_fd &lt; 0), then we pretend to
+   have made a successful write and return 1. */
+int
 binlog_write_job(job j)
 {
-    size_t tube_namelen, to_write;
+    ssize_t written;
+    size_t tube_namelen, to_write = 0;
     struct iovec vec[4], *vptr;
-    int vcnt = 3;
+    int vcnt = 3, r;
 
-    if (binlog_fd &lt; 0) return;
+    if (binlog_fd &lt; 0) return 1;
     tube_namelen = 0;
 
     vec[0].iov_base = (char *) &amp;tube_namelen;
-    vec[0].iov_len = sizeof(size_t);
-    to_write = sizeof(size_t);
+    to_write += vec[0].iov_len = sizeof(size_t);
 
     vec[1].iov_base = j-&gt;tube-&gt;name;
     vec[1].iov_len = 0;
@@ -294,38 +358,42 @@ binlog_write_job(job j)
     /* we could save some bytes in the binlog file by only saving some parts of
      * the job struct */
     vec[2].iov_base = (char *) j;
-    vec[2].iov_len = sizeof(struct job);
-    to_write += sizeof(struct job);
+    to_write += vec[2].iov_len = sizeof(struct job);
+
+    printf(&quot;writing job %lld state %d\n&quot;, j-&gt;id, j-&gt;state);
 
     if (j-&gt;state == JOB_STATE_READY || j-&gt;state == JOB_STATE_DELAYED) {
         if (!j-&gt;binlog) {
             tube_namelen = strlen(j-&gt;tube-&gt;name);
-            vec[1].iov_len = tube_namelen;
-            to_write += tube_namelen;
+            to_write += vec[1].iov_len = tube_namelen;
             vcnt = 4;
             vec[3].iov_base = j-&gt;body;
-            vec[3].iov_len = j-&gt;body_size;
-            to_write += j-&gt;body_size;
+            to_write += vec[3].iov_len = j-&gt;body_size;
         }
     } else if (j-&gt;state == JOB_STATE_INVALID) {
         if (j-&gt;binlog) binlog_dref(j-&gt;binlog);
         j-&gt;binlog = NULL;
     } else {
-        return twarnx(&quot;unserializable job state: %d&quot;, j-&gt;state);
+        return twarnx(&quot;unserializable job state: %d&quot;, j-&gt;state), 0;
     }
 
-    if ((bytes_written + to_write) &gt; binlog_size_limit) binlog_open_next();
-    if (binlog_fd &lt; 0) return;
+    if (to_write &gt; binlog_reserved) {
+        r = binlog_use_next();
+        if (!r) return twarnx(&quot;failed to use next binlog&quot;), 0;
+    }
 
     if (j-&gt;state &amp;&amp; !j-&gt;binlog) j-&gt;binlog = binlog_iref(last_binlog);
 
     while (to_write &gt; 0) {
-        size_t written = writev(binlog_fd, vec, vcnt);
+        written = writev(binlog_fd, vec, vcnt);
 
         if (written &lt; 0) {
-            twarn(&quot;Cannot write to binlog&quot;);
-            binlog_close();
-            return;
+            if (errno == EAGAIN) continue;
+            if (errno == EINTR) continue;
+
+            twarn(&quot;writev&quot;);
+            binlog_close_last();
+            return 0;
         }
 
         bytes_written += written;
@@ -339,8 +407,74 @@ binlog_write_job(job j)
             vptr-&gt;iov_len -= written;
         }
     }
+
+    return 1;
 }
 
+/* Returns the number of bytes successfully reserved: either 0 or n. */
+static size_t
+binlog_reserve_space(size_t n)
+{
+    /* This value must be nonzero but is otherwise ignored. */
+    if (binlog_fd &lt; 0) return 1;
+
+    if (n &lt;= binlog_space) {
+        binlog_space -= n;
+        binlog_reserved += n;
+        return n;
+    }
+
+    if (n &lt;= next_binlog_space) {
+        next_binlog_space -= n;
+        next_binlog_reserved += n;
+        return n;
+    }
+
+    /* The next binlog is already allocated and it is full. */
+    if (next_binlog_fd &gt;= 0) return 0;
+
+    /* open a new binlog with more space to reserve */
+    next_binlog = make_next_binlog();
+    if (!next_binlog) return twarnx(&quot;error making next binlog&quot;), 0;
+    next_binlog_fd = binlog_open(next_binlog);
+
+    /* open failed, so we can't reserve any space */
+    if (next_binlog_fd &lt; 0) return 0;
+
+    next_binlog_space = binlog_size_limit - bytes_written - n;
+    next_binlog_reserved = n;
+
+    return n;
+}
+
+/* Returns the number of bytes reserved. */
+size_t
+binlog_reserve_space_put(job j)
+{
+    size_t z = 0;
+
+    /* reserve space for the initial job record */
+    z += sizeof(size_t);
+    z += strlen(j-&gt;tube-&gt;name);
+    z += sizeof(struct job);
+    z += j-&gt;body_size;
+
+    /* plus space for a delete to come later */
+    z += sizeof(size_t);
+    z += sizeof(struct job);
+
+    return binlog_reserve_space(z);
+}
+
+size_t
+binlog_reserve_space_update(job j)
+{
+    size_t z = 0;
+
+    z += sizeof(size_t);
+    z += sizeof(struct job);
+    return binlog_reserve_space(z);
+}
 
 void
 binlog_read(job binlog_jobs)
@@ -372,7 +506,7 @@ binlog_read(job binlog_jobs)
             if (fd &lt; 0) {
                 twarn(&quot;%s&quot;, path);
             } else {
-                b = binlog_iref(add_binlog(path));
+                b = binlog_iref(add_binlog(make_binlog(path)));
                 binlog_read_one(fd, binlog_jobs, path);
                 close(fd);
                 binlog_dref(b);
@@ -408,7 +542,14 @@ binlog_lock()
 void
 binlog_init()
 {
-    binlog_fd = binlog_open();
+    binlog log;
+
+    if (!binlog_dir) return;
+
+    log = make_next_binlog();
+    if (!log) return twarnx(&quot;error making first binlog&quot;);
+    binlog_fd = binlog_open(log);
+    if (binlog_fd &gt;= 0) add_binlog(log);
 }
 
 const char *</diff>
      <filename>binlog.c</filename>
    </modified>
    <modified>
      <diff>@@ -32,10 +32,16 @@ struct binlog {
 extern char *binlog_dir;
 extern size_t binlog_size_limit;
 
+void binlog_init();
+
 /* Return the number of locks acquired: either 0 or 1. */
 int binlog_lock();
 
-void binlog_write_job(job j);
+/* Returns the number of jobs successfully written (either 0 or 1). */
+int binlog_write_job(job j);
+size_t binlog_reserve_space_put(job j);
+size_t binlog_reserve_space_update(job j);
+
 void binlog_read(job binlog_jobs);
 void binlog_close();
 const char *binlog_oldest_index();</diff>
      <filename>binlog.h</filename>
    </modified>
    <modified>
      <diff>@@ -118,6 +118,7 @@ allocate_job(int body_size)
     j-&gt;tube = NULL;
     j-&gt;binlog = NULL;
     j-&gt;heap_index = 0;
+    j-&gt;reserved_binlog_space = 0;
 
     return j;
 }</diff>
      <filename>job.c</filename>
    </modified>
    <modified>
      <diff>@@ -32,8 +32,11 @@ typedef int(*job_cmp_fn)(job, job);
 #define JOB_STATE_BURIED 3
 #define JOB_STATE_DELAYED 4
 
+/* If you modify this struct, you MUST increment binlog format version in
+ * binlog.c. */
 struct job {
-    job prev, next; /* linked list of jobs */
+
+    /* persistent fields; these get written to the binlog */
     unsigned long long int id;
     unsigned int pri;
     unsigned int delay;
@@ -45,12 +48,19 @@ struct job {
     unsigned int release_ct;
     unsigned int bury_ct;
     unsigned int kick_ct;
-    tube tube;
-    void *reserver;
-    void *binlog;
     char state;
+
+    /* bookeeping fields; these are in-memory only */
+    char pad[6];
+    tube tube;
+    job prev, next; /* linked list of jobs */
     job ht_next; /* Next job in a hash table list */
-    size_t heap_index; /* where is this job in a heap */
+    size_t heap_index; /* where is this job in its current heap */
+    void *binlog;
+    void *reserver;
+    size_t reserved_binlog_space;
+
+    /* variable-size job data; written separately to the binlog */
     char body[];
 };
 </diff>
      <filename>job.h</filename>
    </modified>
    <modified>
      <diff>@@ -426,7 +426,7 @@ set_main_delay_timeout()
 }
 
 static int
-enqueue_job(job j, unsigned int delay)
+enqueue_job(job j, unsigned int delay, char update_store)
 {
     int r;
 
@@ -447,21 +447,37 @@ enqueue_job(job j, unsigned int delay)
             j-&gt;tube-&gt;stat.urgent_ct++;
         }
     }
-    binlog_write_job(j);
+
+    if (update_store) {
+        r = binlog_write_job(j);
+        if (!r) return -1;
+    }
+
     process_queue();
     return 1;
 }
 
-static void
-bury_job(job j)
+static int
+bury_job(job j, char update_store)
 {
+    size_t z;
+
+    if (update_store) {
+        z = binlog_reserve_space_update(j);
+        if (!z) return 0;
+        j-&gt;reserved_binlog_space += z;
+    }
+
     job_insert(&amp;j-&gt;tube-&gt;buried, j);
     global_stat.buried_ct++;
     j-&gt;tube-&gt;stat.buried_ct++;
     j-&gt;state = JOB_STATE_BURIED;
     j-&gt;reserver = NULL;
     j-&gt;bury_ct++;
-    binlog_write_job(j);
+
+    if (update_store) return binlog_write_job(j);
+
+    return 1;
 }
 
 void
@@ -472,8 +488,8 @@ enqueue_reserved_jobs(conn c)
 
     while (job_list_any_p(&amp;c-&gt;reserved_jobs)) {
         j = job_remove(c-&gt;reserved_jobs.next);
-        r = enqueue_job(j, 0);
-        if (!r) bury_job(j);
+        r = enqueue_job(j, 0, 0);
+        if (r &lt; 1) bury_job(j, 0);
         global_stat.reserved_ct--;
         j-&gt;tube-&gt;stat.reserved_ct--;
         c-&gt;soonest_job = NULL;
@@ -493,15 +509,21 @@ kick_buried_job(tube t)
 {
     int r;
     job j;
+    size_t z;
 
     if (!buried_job_p(t)) return 0;
     j = remove_buried_job(t-&gt;buried.next);
+
+    z = binlog_reserve_space_update(j);
+    if (!z) return pq_give(&amp;t-&gt;delay, j), 0; /* put it back */
+    j-&gt;reserved_binlog_space += z;
+
     j-&gt;kick_ct++;
-    r = enqueue_job(j, 0);
-    if (r) return 1;
+    r = enqueue_job(j, 0, 1);
+    if (r == 1) return 1;
 
     /* ready queue is full, so bury it */
-    bury_job(j);
+    bury_job(j, 0);
     return 0;
 }
 
@@ -524,19 +546,25 @@ kick_delayed_job(tube t)
 {
     int r;
     job j;
+    size_t z;
 
     j = pq_take(&amp;t-&gt;delay);
     if (!j) return 0;
+
+    z = binlog_reserve_space_update(j);
+    if (!z) return pq_give(&amp;t-&gt;delay, j), 0; /* put it back */
+    j-&gt;reserved_binlog_space += z;
+
     j-&gt;kick_ct++;
-    r = enqueue_job(j, 0);
-    if (r) return 1;
+    r = enqueue_job(j, 0, 1);
+    if (r == 1) return 1;
 
     /* ready queue is full, so delay it again */
-    r = enqueue_job(j, j-&gt;delay);
-    if (r) return 0;
+    r = enqueue_job(j, j-&gt;delay, 0);
+    if (r == 1) return 0;
 
     /* last resort */
-    bury_job(j);
+    bury_job(j, 0);
     return 0;
 }
 
@@ -745,16 +773,22 @@ enqueue_incoming_job(conn c)
         return reply_serr(c, MSG_DRAINING);
     }
 
+    if (j-&gt;reserved_binlog_space) return reply_serr(c, MSG_INTERNAL_ERROR);
+    j-&gt;reserved_binlog_space = binlog_reserve_space_put(j);
+    if (!j-&gt;reserved_binlog_space) return reply_serr(c, MSG_OUT_OF_MEMORY);
+
     /* we have a complete job, so let's stick it in the pqueue */
-    r = enqueue_job(j, j-&gt;delay);
+    r = enqueue_job(j, j-&gt;delay, 1);
+    if (r &lt; 0) return reply_serr(c, MSG_INTERNAL_ERROR);
+
     op_ct[OP_PUT]++; /* stats */
     global_stat.total_jobs_ct++;
     j-&gt;tube-&gt;stat.total_jobs_ct++;
 
-    if (r) return reply_line(c, STATE_SENDWORD, MSG_INSERTED_FMT, j-&gt;id);
+    if (r == 1) return reply_line(c, STATE_SENDWORD, MSG_INSERTED_FMT, j-&gt;id);
 
     /* out of memory trying to grow the queue, so it gets buried */
-    bury_job(j);
+    bury_job(j, 0);
     reply_line(c, STATE_SENDWORD, MSG_BURIED_FMT, j-&gt;id);
 }
 
@@ -1019,6 +1053,7 @@ static void
 dispatch_cmd(conn c)
 {
     int r, i, timeout = -1;
+    size_t z;
     unsigned int count;
     job j;
     unsigned char type;
@@ -1174,9 +1209,11 @@ dispatch_cmd(conn c)
         if (!j) return reply(c, MSG_NOTFOUND, MSG_NOTFOUND_LEN, STATE_SENDWORD);
 
         j-&gt;state = JOB_STATE_INVALID;
-        binlog_write_job(j);
+        r = binlog_write_job(j);
         job_free(j);
 
+        if (!r) return reply_serr(c, MSG_INTERNAL_ERROR);
+
         reply(c, MSG_DELETED, MSG_DELETED_LEN, STATE_SENDWORD);
         break;
     case OP_RELEASE:
@@ -1195,14 +1232,26 @@ dispatch_cmd(conn c)
 
         if (!j) return reply(c, MSG_NOTFOUND, MSG_NOTFOUND_LEN, STATE_SENDWORD);
 
+        /* We want to update the delay deadline on disk, so reserve space for
+         * that. */
+        if (delay) {
+            z = binlog_reserve_space_update(j);
+            if (!z) return reply_serr(c, MSG_OUT_OF_MEMORY);
+            j-&gt;reserved_binlog_space += z;
+        }
+
         j-&gt;pri = pri;
         j-&gt;delay = delay;
         j-&gt;release_ct++;
-        r = enqueue_job(j, delay);
-        if (r) return reply(c, MSG_RELEASED, MSG_RELEASED_LEN, STATE_SENDWORD);
+
+        r = enqueue_job(j, delay, !!delay);
+        if (r &lt; 0) return reply_serr(c, MSG_INTERNAL_ERROR);
+        if (r == 1) {
+            return reply(c, MSG_RELEASED, MSG_RELEASED_LEN, STATE_SENDWORD);
+        }
 
         /* out of memory trying to grow the queue, so it gets buried */
-        bury_job(j);
+        bury_job(j, 0);
         reply(c, MSG_BURIED, MSG_BURIED_LEN, STATE_SENDWORD);
         break;
     case OP_BURY:
@@ -1219,7 +1268,8 @@ dispatch_cmd(conn c)
         if (!j) return reply(c, MSG_NOTFOUND, MSG_NOTFOUND_LEN, STATE_SENDWORD);
 
         j-&gt;pri = pri;
-        bury_job(j);
+        r = bury_job(j, 1);
+        if (!r) return reply_serr(c, MSG_INTERNAL_ERROR);
         reply(c, MSG_BURIED, MSG_BURIED_LEN, STATE_SENDWORD);
         break;
     case OP_KICK:
@@ -1399,8 +1449,8 @@ h_conn_timeout(conn c)
 
         timeout_ct++; /* stats */
         j-&gt;timeout_ct++;
-        r = enqueue_job(remove_this_reserved_job(c, j), 0);
-        if (!r) bury_job(j); /* there was no room in the queue, so bury it */
+        r = enqueue_job(remove_this_reserved_job(c, j), 0, 0);
+        if (r &lt; 1) bury_job(j, 0); /* out of memory, so bury it */
         r = conn_update_evq(c, c-&gt;evq.ev_events);
         if (r == -1) return twarnx(&quot;conn_update_evq() failed&quot;), conn_close(c);
     }
@@ -1590,8 +1640,8 @@ h_delay()
     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 */
+        r = enqueue_job(j, 0, 0);
+        if (r &lt; 1) bury_job(j, 0); /* out of memory, so bury it */
     }
 
     set_main_delay_timeout();
@@ -1642,28 +1692,27 @@ prot_init()
 }
 
 void
-prot_replay_binlog()
+prot_replay_binlog(job binlog_jobs)
 {
-    struct job binlog_jobs;
     job j, nj;
     unsigned int delay;
+    int r;
 
-    binlog_jobs.prev = binlog_jobs.next = &amp;binlog_jobs;
-    binlog_read(&amp;binlog_jobs);
-
-    for (j = binlog_jobs.next ; j != &amp;binlog_jobs ; j = nj) {
+    for (j = binlog_jobs-&gt;next ; j != binlog_jobs ; j = nj) {
         nj = j-&gt;next;
         job_remove(j);
+        binlog_reserve_space_update(j); /* reserve space for a delete */
         delay = 0;
         switch (j-&gt;state) {
         case JOB_STATE_BURIED:
-            bury_job(j);
+            bury_job(j, 0);
             break;
         case JOB_STATE_DELAYED:
             if (start_time &lt; j-&gt;deadline) delay = j-&gt;deadline - start_time;
             /* fall through */
         default:
-            enqueue_job(j,delay);
+            r = enqueue_job(j, delay, 0);
+            if (r &lt; 1) twarnx(&quot;error processing binlog job %llu&quot;, j-&gt;id);
         }
     }
 }</diff>
      <filename>prot.c</filename>
    </modified>
    <modified>
      <diff>@@ -35,6 +35,6 @@ void enqueue_reserved_jobs(conn c);
 void enter_drain_mode(int sig);
 void h_accept(const int fd, const short which, struct event *ev);
 void prot_remove_tube(tube t);
-void prot_replay_binlog();
+void prot_replay_binlog(job binlog_jobs);
 
 #endif /*prot_h*/</diff>
      <filename>prot.h</filename>
    </modified>
    <modified>
      <diff>@@ -43,7 +43,8 @@ make_tube(const char *name)
 
     pq_init(&amp;t-&gt;ready, job_pri_cmp);
     pq_init(&amp;t-&gt;delay, job_delay_cmp);
-    t-&gt;buried = (struct job) { &amp;t-&gt;buried, &amp;t-&gt;buried, 0 };
+    t-&gt;buried = (struct job) { };
+    t-&gt;buried.prev = t-&gt;buried.next = &amp;t-&gt;buried;
     ms_init(&amp;t-&gt;waiting, NULL, NULL);
 
     t-&gt;stat = (struct stats) {0, 0, 0, 0};</diff>
      <filename>tube.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>8313430cdc94eebc9eb66b95c41d46a49fff0df9</id>
    </parent>
  </parents>
  <author>
    <name>Keith Rarick</name>
    <email>kr@xph.us</email>
  </author>
  <url>http://github.com/kr/beanstalkd/commit/12299e05b4a0e472c97fe73073d5e2d5bcecd5a7</url>
  <id>12299e05b4a0e472c97fe73073d5e2d5bcecd5a7</id>
  <committed-date>2009-05-05T16:55:06-07:00</committed-date>
  <authored-date>2009-01-17T10:56:10-08:00</authored-date>
  <message>Allocate disk space more carefully. Closes gh-1.</message>
  <tree>c9e9f28c41d21b7dbd38f7ca25b1fc4917f21001</tree>
  <committer>
    <name>Keith Rarick</name>
    <email>kr@xph.us</email>
  </committer>
</commit>
