ctdb-daemon: Drop the "schedule for deletion" messages to DEBUG level
[obnox/samba/samba-obnox.git] / ctdb / server / ctdb_vacuum.c
index 7d2a6b4a870f541bcc29365242bfe8a4df884b11..f53612935469c7ea545cc577d3db3d796b8aa2d9 100644 (file)
    along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "includes.h"
-#include "tdb.h"
+#include "replace.h"
 #include "system/network.h"
 #include "system/filesys.h"
-#include "system/dir.h"
-#include "../include/ctdb_private.h"
-#include "db_wrap.h"
+#include "system/time.h"
+
+#include <talloc.h>
+#include <tevent.h>
+
+#include "lib/tdb_wrap/tdb_wrap.h"
 #include "lib/util/dlinklist.h"
-#include "../include/ctdb_private.h"
-#include "../common/rb_tree.h"
+#include "lib/util/debug.h"
+#include "lib/util/samba_util.h"
+#include "lib/util/util_process.h"
+
+#include "ctdb_private.h"
+#include "ctdb_client.h"
+
+#include "common/rb_tree.h"
+#include "common/system.h"
+#include "common/common.h"
+#include "common/logging.h"
 
 #define TIMELIMIT() timeval_current_ofs(10, 0)
 
@@ -53,34 +64,42 @@ struct ctdb_vacuum_handle {
 
 /*  a list of records to possibly delete */
 struct vacuum_data {
-       uint32_t repack_limit;
        struct ctdb_context *ctdb;
        struct ctdb_db_context *ctdb_db;
        struct tdb_context *dest_db;
        trbt_tree_t *delete_list;
-       uint32_t delete_count;
        struct ctdb_marshall_buffer **vacuum_fetch_list;
        struct timeval start;
        bool traverse_error;
        bool vacuum;
-       uint32_t total;
-       uint32_t vacuumed;
-       uint32_t copied;
-       uint32_t fast_added_to_vacuum_fetch_list;
-       uint32_t fast_added_to_delete_list;
-       uint32_t fast_deleted;
-       uint32_t fast_skipped;
-       uint32_t fast_error;
-       uint32_t fast_total;
-       uint32_t full_scheduled;
-       uint32_t full_skipped;
-       uint32_t full_error;
-       uint32_t full_total;
-       uint32_t delete_left;
-       uint32_t delete_remote_error;
-       uint32_t delete_local_error;
-       uint32_t delete_deleted;
-       uint32_t delete_skipped;
+       struct {
+               struct {
+                       uint32_t added_to_vacuum_fetch_list;
+                       uint32_t added_to_delete_list;
+                       uint32_t deleted;
+                       uint32_t skipped;
+                       uint32_t error;
+                       uint32_t total;
+               } delete_queue;
+               struct {
+                       uint32_t scheduled;
+                       uint32_t skipped;
+                       uint32_t error;
+                       uint32_t total;
+               } db_traverse;
+               struct {
+                       uint32_t total;
+                       uint32_t remote_error;
+                       uint32_t local_error;
+                       uint32_t deleted;
+                       uint32_t skipped;
+                       uint32_t left;
+               } delete_list;
+               struct {
+                       uint32_t vacuumed;
+                       uint32_t copied;
+               } repack;
+       } count;
 };
 
 /* this structure contains the information for one record to be deleted */
@@ -160,7 +179,7 @@ static int add_record_to_delete_list(struct vacuum_data *vdata, TDB_DATA key,
                return -1;
        }
 
-       vdata->delete_count++;
+       vdata->count.delete_list.total++;
 
        return 0;
 }
@@ -173,42 +192,29 @@ static int add_record_to_vacuum_fetch_list(struct vacuum_data *vdata,
                                           TDB_DATA key)
 {
        struct ctdb_context *ctdb = vdata->ctdb;
-       struct ctdb_rec_data *rec;
        uint32_t lmaster;
-       size_t old_size;
        struct ctdb_marshall_buffer *vfl;
 
        lmaster = ctdb_lmaster(ctdb, &key);
 
        vfl = vdata->vacuum_fetch_list[lmaster];
 
-       rec = ctdb_marshall_record(vfl, ctdb->pnn, key, NULL, tdb_null);
-       if (rec == NULL) {
+       vfl = ctdb_marshall_add(ctdb, vfl, vfl->db_id, ctdb->pnn,
+                               key, NULL, tdb_null);
+       if (vfl == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
                vdata->traverse_error = true;
                return -1;
        }
 
-       old_size = talloc_get_size(vfl);
-       vfl = talloc_realloc_size(NULL, vfl, old_size + rec->length);
-       if (vfl == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to expand\n"));
-               vdata->traverse_error = true;
-               return -1;
-       }
        vdata->vacuum_fetch_list[lmaster] = vfl;
 
-       vfl->count++;
-       memcpy(old_size+(uint8_t *)vfl, rec, rec->length);
-       talloc_free(rec);
-
-       vdata->total++;
-
        return 0;
 }
 
 
-static void ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
+static void ctdb_vacuum_event(struct tevent_context *ev,
+                             struct tevent_timer *te,
                              struct timeval t, void *private_data);
 
 static int vacuum_record_parser(TDB_DATA key, TDB_DATA data, void *private_data)
@@ -239,11 +245,11 @@ static int vacuum_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
        struct ctdb_ltdb_header *hdr;
        int res = 0;
 
-       vdata->full_total++;
+       vdata->count.db_traverse.total++;
 
        lmaster = ctdb_lmaster(ctdb, &key);
        if (lmaster >= ctdb->num_nodes) {
-               vdata->full_error++;
+               vdata->count.db_traverse.error++;
                DEBUG(DEBUG_CRIT, (__location__
                                   " lmaster[%u] >= ctdb->num_nodes[%u] for key"
                                   " with hash[%u]!\n",
@@ -255,14 +261,14 @@ static int vacuum_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
 
        if (data.dsize != sizeof(struct ctdb_ltdb_header)) {
                /* it is not a deleted record */
-               vdata->full_skipped++;
+               vdata->count.db_traverse.skipped++;
                return 0;
        }
 
        hdr = (struct ctdb_ltdb_header *)data.dptr;
 
        if (hdr->dmaster != ctdb->pnn) {
-               vdata->full_skipped++;
+               vdata->count.db_traverse.skipped++;
                return 0;
        }
 
@@ -272,9 +278,9 @@ static int vacuum_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
         */
        res = insert_record_into_delete_queue(ctdb_db, hdr, key);
        if (res != 0) {
-               vdata->full_error++;
+               vdata->count.db_traverse.error++;
        } else {
-               vdata->full_scheduled++;
+               vdata->count.db_traverse.scheduled++;
        }
 
        return 0;
@@ -288,23 +294,17 @@ static int delete_marshall_traverse(void *param, void *data)
 {
        struct delete_record_data *dd = talloc_get_type(data, struct delete_record_data);
        struct delete_records_list *recs = talloc_get_type(param, struct delete_records_list);
-       struct ctdb_rec_data *rec;
-       size_t old_size;
+       struct ctdb_marshall_buffer *m;
 
-       rec = ctdb_marshall_record(dd, recs->records->db_id, dd->key, &dd->hdr, tdb_null);
-       if (rec == NULL) {
+       m = ctdb_marshall_add(recs, recs->records, recs->records->db_id,
+                             recs->records->db_id,
+                             dd->key, &dd->hdr, tdb_null);
+       if (m == NULL) {
                DEBUG(DEBUG_ERR, (__location__ " failed to marshall record\n"));
-               return 0;
+               return -1;
        }
 
-       old_size = talloc_get_size(recs->records);
-       recs->records = talloc_realloc_size(NULL, recs->records, old_size + rec->length);
-       if (recs->records == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to expand\n"));
-               return 0;
-       }
-       recs->records->count++;
-       memcpy(old_size+(uint8_t *)(recs->records), rec, rec->length);
+       recs->records = m;
        return 0;
 }
 
@@ -329,13 +329,10 @@ static int delete_marshall_traverse_first(void *param, void *data)
        uint32_t hash = ctdb_hash(&(dd->key));
        int res;
 
-       res = tdb_chainlock(ctdb_db->ltdb->tdb, dd->key);
+       res = tdb_chainlock_nonblock(ctdb_db->ltdb->tdb, dd->key);
        if (res != 0) {
-               DEBUG(DEBUG_ERR,
-                     (__location__ " Error getting chainlock on record with "
-                      "key hash [0x%08x] on database db[%s].\n",
-                      hash, ctdb_db->db_name));
-               recs->vdata->delete_skipped++;
+               recs->vdata->count.delete_list.skipped++;
+               recs->vdata->count.delete_list.left--;
                talloc_free(dd);
                return 0;
        }
@@ -410,7 +407,8 @@ static int delete_marshall_traverse_first(void *param, void *data)
 skip:
        tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
 
-       recs->vdata->delete_skipped++;
+       recs->vdata->count.delete_list.skipped++;
+       recs->vdata->count.delete_list.left--;
        talloc_free(dd);
        dd = NULL;
 
@@ -454,15 +452,11 @@ static int delete_queue_traverse(void *param, void *data)
        uint32_t lmaster;
        uint32_t hash = ctdb_hash(&(dd->key));
 
-       vdata->fast_total++;
+       vdata->count.delete_queue.total++;
 
-       res = tdb_chainlock(ctdb_db->ltdb->tdb, dd->key);
+       res = tdb_chainlock_nonblock(ctdb_db->ltdb->tdb, dd->key);
        if (res != 0) {
-               DEBUG(DEBUG_ERR,
-                     (__location__ " Error getting chainlock on record with "
-                      "key hash [0x%08x] on database db[%s].\n",
-                      hash, ctdb_db->db_name));
-               vdata->fast_error++;
+               vdata->count.delete_queue.error++;
                return 0;
        }
 
@@ -503,9 +497,9 @@ static int delete_queue_traverse(void *param, void *data)
                        DEBUG(DEBUG_ERR,
                              (__location__ " Error adding record to list "
                               "of records to send to lmaster.\n"));
-                       vdata->fast_error++;
+                       vdata->count.delete_queue.error++;
                } else {
-                       vdata->fast_added_to_vacuum_fetch_list++;
+                       vdata->count.delete_queue.added_to_vacuum_fetch_list++;
                }
                goto done;
        }
@@ -518,9 +512,9 @@ static int delete_queue_traverse(void *param, void *data)
                        DEBUG(DEBUG_ERR,
                              (__location__ " Error adding record to list "
                               "of records for deletion on lmaster.\n"));
-                       vdata->fast_error++;
+                       vdata->count.delete_queue.error++;
                } else {
-                       vdata->fast_added_to_delete_list++;
+                       vdata->count.delete_queue.added_to_delete_list++;
                }
        } else {
                res = tdb_delete(ctdb_db->ltdb->tdb, dd->key);
@@ -530,7 +524,7 @@ static int delete_queue_traverse(void *param, void *data)
                              (__location__ " Error deleting record with key "
                               "hash [0x%08x] from local data base db[%s].\n",
                               hash, ctdb_db->db_name));
-                       vdata->fast_error++;
+                       vdata->count.delete_queue.error++;
                        goto done;
                }
 
@@ -538,13 +532,13 @@ static int delete_queue_traverse(void *param, void *data)
                      (__location__ " Deleted record with key hash "
                       "[0x%08x] from local data base db[%s].\n",
                       hash, ctdb_db->db_name));
-               vdata->fast_deleted++;
+               vdata->count.delete_queue.deleted++;
        }
 
        goto done;
 
 skipped:
-       vdata->fast_skipped++;
+       vdata->count.delete_queue.skipped++;
 
 done:
        tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
@@ -575,8 +569,8 @@ static int delete_record_traverse(void *param, void *data)
                      (__location__ " Error getting chainlock on record with "
                       "key hash [0x%08x] on database db[%s].\n",
                       hash, ctdb_db->db_name));
-               vdata->delete_local_error++;
-               vdata->delete_left--;
+               vdata->count.delete_list.local_error++;
+               vdata->count.delete_list.left--;
                talloc_free(dd);
                return 0;
        }
@@ -640,7 +634,7 @@ static int delete_record_traverse(void *param, void *data)
                      (__location__ " Error deleting record with key hash "
                       "[0x%08x] from local data base db[%s].\n",
                       hash, ctdb_db->db_name));
-               vdata->delete_local_error++;
+               vdata->count.delete_list.local_error++;
                goto done;
        }
 
@@ -648,17 +642,17 @@ static int delete_record_traverse(void *param, void *data)
              (__location__ " Deleted record with key hash [0x%08x] from "
               "local data base db[%s].\n", hash, ctdb_db->db_name));
 
-       vdata->delete_deleted++;
+       vdata->count.delete_list.deleted++;
        goto done;
 
 skip:
-       vdata->delete_skipped++;
+       vdata->count.delete_list.skipped++;
 
 done:
        tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
 
        talloc_free(dd);
-       vdata->delete_left--;
+       vdata->count.delete_list.left--;
 
        return 0;
 }
@@ -673,23 +667,31 @@ static void ctdb_process_delete_queue(struct ctdb_db_context *ctdb_db,
                                      struct vacuum_data *vdata)
 {
        uint32_t sum;
+       int ret;
+
+       ret = trbt_traversearray32(ctdb_db->delete_queue, 1,
+                                  delete_queue_traverse, vdata);
 
-       trbt_traversearray32(ctdb_db->delete_queue, 1, delete_queue_traverse, vdata);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, (__location__ " Error traversing "
+                     "the delete queue.\n"));
+       }
 
-       sum = vdata->fast_deleted
-           + vdata->fast_skipped
-           + vdata->fast_error
-           + vdata->fast_added_to_delete_list
-           + vdata->fast_added_to_vacuum_fetch_list;
+       sum = vdata->count.delete_queue.deleted
+           + vdata->count.delete_queue.skipped
+           + vdata->count.delete_queue.error
+           + vdata->count.delete_queue.added_to_delete_list
+           + vdata->count.delete_queue.added_to_vacuum_fetch_list;
 
-       if (vdata->fast_total != sum) {
+       if (vdata->count.delete_queue.total != sum) {
                DEBUG(DEBUG_ERR, (__location__ " Inconsistency in fast vacuum "
                      "counts for db[%s]: total[%u] != sum[%u]\n",
-                     ctdb_db->db_name, (unsigned)vdata->fast_total,
+                     ctdb_db->db_name,
+                     (unsigned)vdata->count.delete_queue.total,
                      (unsigned)sum));
        }
 
-       if (vdata->fast_total > 0) {
+       if (vdata->count.delete_queue.total > 0) {
                DEBUG(DEBUG_INFO,
                      (__location__
                       " fast vacuuming delete_queue traverse statistics: "
@@ -701,12 +703,12 @@ static void ctdb_process_delete_queue(struct ctdb_db_context *ctdb_db,
                       "adl[%u] "
                       "avf[%u]\n",
                       ctdb_db->db_name,
-                      (unsigned)vdata->fast_total,
-                      (unsigned)vdata->fast_deleted,
-                      (unsigned)vdata->fast_skipped,
-                      (unsigned)vdata->fast_error,
-                      (unsigned)vdata->fast_added_to_delete_list,
-                      (unsigned)vdata->fast_added_to_vacuum_fetch_list));
+                      (unsigned)vdata->count.delete_queue.total,
+                      (unsigned)vdata->count.delete_queue.deleted,
+                      (unsigned)vdata->count.delete_queue.skipped,
+                      (unsigned)vdata->count.delete_queue.error,
+                      (unsigned)vdata->count.delete_queue.added_to_delete_list,
+                      (unsigned)vdata->count.delete_queue.added_to_vacuum_fetch_list));
        }
 
        return;
@@ -719,8 +721,8 @@ static void ctdb_process_delete_queue(struct ctdb_db_context *ctdb_db,
  * This is not done each time but only every tunable
  * VacuumFastPathCount times.
  */
-static int ctdb_vacuum_traverse_db(struct ctdb_db_context *ctdb_db,
-                                  struct vacuum_data *vdata)
+static void ctdb_vacuum_traverse_db(struct ctdb_db_context *ctdb_db,
+                                   struct vacuum_data *vdata)
 {
        int ret;
 
@@ -728,10 +730,10 @@ static int ctdb_vacuum_traverse_db(struct ctdb_db_context *ctdb_db,
        if (ret == -1 || vdata->traverse_error) {
                DEBUG(DEBUG_ERR, (__location__ " Traverse error in vacuuming "
                                  "'%s'\n", ctdb_db->db_name));
-               return -1;
+               return;
        }
 
-       if (vdata->full_total > 0) {
+       if (vdata->count.db_traverse.total > 0) {
                DEBUG(DEBUG_INFO,
                      (__location__
                       " full vacuuming db traverse statistics: "
@@ -741,13 +743,13 @@ static int ctdb_vacuum_traverse_db(struct ctdb_db_context *ctdb_db,
                       "err[%u] "
                       "sched[%u]\n",
                       ctdb_db->db_name,
-                      (unsigned)vdata->full_total,
-                      (unsigned)vdata->full_skipped,
-                      (unsigned)vdata->full_error,
-                      (unsigned)vdata->full_scheduled));
+                      (unsigned)vdata->count.db_traverse.total,
+                      (unsigned)vdata->count.db_traverse.skipped,
+                      (unsigned)vdata->count.db_traverse.error,
+                      (unsigned)vdata->count.db_traverse.scheduled));
        }
 
-       return 0;
+       return;
 }
 
 /**
@@ -755,8 +757,8 @@ static int ctdb_vacuum_traverse_db(struct ctdb_db_context *ctdb_db,
  * For records for which we are not the lmaster, tell the lmaster to
  * fetch the record.
  */
-static int ctdb_process_vacuum_fetch_lists(struct ctdb_db_context *ctdb_db,
-                                          struct vacuum_data *vdata)
+static void ctdb_process_vacuum_fetch_lists(struct ctdb_db_context *ctdb_db,
+                                           struct vacuum_data *vdata)
 {
        int i;
        struct ctdb_context *ctdb = ctdb_db->ctdb;
@@ -777,8 +779,7 @@ static int ctdb_process_vacuum_fetch_lists(struct ctdb_db_context *ctdb_db,
                                   vfl->count, ctdb->nodes[i]->pnn,
                                   ctdb_db->db_name));
 
-               data.dsize = talloc_get_size(vfl);
-               data.dptr  = (void *)vfl;
+               data = ctdb_marshall_finish(vfl);
                if (ctdb_client_send_message(ctdb, ctdb->nodes[i]->pnn,
                                             CTDB_SRVID_VACUUM_FETCH,
                                             data) != 0)
@@ -786,11 +787,10 @@ static int ctdb_process_vacuum_fetch_lists(struct ctdb_db_context *ctdb_db,
                        DEBUG(DEBUG_ERR, (__location__ " Failed to send vacuum "
                                          "fetch message to %u\n",
                                          ctdb->nodes[i]->pnn));
-                       return -1;
                }
        }
 
-       return 0;
+       return;
 }
 
 /**
@@ -816,30 +816,30 @@ static int ctdb_process_vacuum_fetch_lists(struct ctdb_db_context *ctdb_db,
  *  3) The lmaster locally deletes its copies of all records that
  *     could successfully be deleted remotely in step #2.
  */
-static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
-                                   struct vacuum_data *vdata)
+static void ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
+                                    struct vacuum_data *vdata)
 {
        int ret, i;
        struct ctdb_context *ctdb = ctdb_db->ctdb;
        struct delete_records_list *recs;
        TDB_DATA indata;
-       struct ctdb_node_map *nodemap;
+       struct ctdb_node_map_old *nodemap;
        uint32_t *active_nodes;
        int num_active_nodes;
        TALLOC_CTX *tmp_ctx;
        uint32_t sum;
 
-       if (vdata->delete_count == 0) {
-               return 0;
+       if (vdata->count.delete_list.total == 0) {
+               return;
        }
 
        tmp_ctx = talloc_new(vdata);
        if (tmp_ctx == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               return 0;
+               return;
        }
 
-       vdata->delete_left = vdata->delete_count;
+       vdata->count.delete_list.left = vdata->count.delete_list.total;
 
        /*
         * get the list of currently active nodes
@@ -851,7 +851,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                                   &nodemap);
        if (ret != 0) {
                DEBUG(DEBUG_ERR,(__location__ " unable to get node map\n"));
-               ret = -1;
                goto done;
        }
 
@@ -878,7 +877,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
        recs = talloc_zero(tmp_ctx, struct delete_records_list);
        if (recs == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               ret = -1;
                goto done;
        }
        recs->records = (struct ctdb_marshall_buffer *)
@@ -886,7 +884,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                                 offsetof(struct ctdb_marshall_buffer, data));
        if (recs->records == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               ret = -1;
                goto done;
        }
        recs->records->db_id = ctdb_db->db_id;
@@ -900,15 +897,19 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
         * records' RSNs in the database, to ensure we (as dmaster)
         * keep the highest RSN of the records in the cluster.
         */
-       trbt_traversearray32(vdata->delete_list, 1,
-                            delete_marshall_traverse_first, recs);
+       ret = trbt_traversearray32(vdata->delete_list, 1,
+                                  delete_marshall_traverse_first, recs);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, (__location__ " Error traversing the "
+                     "delete list for first marshalling.\n"));
+               goto done;
+       }
 
-       indata.dsize = talloc_get_size(recs->records);
-       indata.dptr  = (void *)recs->records;
+       indata = ctdb_marshall_finish(recs->records);
 
        for (i = 0; i < num_active_nodes; i++) {
                struct ctdb_marshall_buffer *records;
-               struct ctdb_rec_data *rec;
+               struct ctdb_rec_data_old *rec;
                int32_t res;
                TDB_DATA outdata;
 
@@ -920,7 +921,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                        DEBUG(DEBUG_ERR, ("Error storing record copies on "
                                          "node %u: ret[%d] res[%d]\n",
                                          active_nodes[i], ret, res));
-                       ret = -1;
                        goto done;
                }
 
@@ -931,7 +931,7 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                 * the list to process further.
                 */
                records = (struct ctdb_marshall_buffer *)outdata.dptr;
-               rec = (struct ctdb_rec_data *)&records->data[0];
+               rec = (struct ctdb_rec_data_old *)&records->data[0];
                while (records->count-- > 1) {
                        TDB_DATA reckey, recdata;
                        struct ctdb_ltdb_header *rechdr;
@@ -944,7 +944,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
 
                        if (recdata.dsize < sizeof(struct ctdb_ltdb_header)) {
                                DEBUG(DEBUG_CRIT,(__location__ " bad ltdb record\n"));
-                               ret = -1;
                                goto done;
                        }
                        rechdr = (struct ctdb_ltdb_header *)recdata.dptr;
@@ -962,15 +961,23 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                                 * update statistics.
                                 */
                                talloc_free(dd);
-                               vdata->delete_remote_error++;
-                               vdata->delete_left--;
+                               vdata->count.delete_list.remote_error++;
+                               vdata->count.delete_list.left--;
+                       } else {
+                               DEBUG(DEBUG_ERR, (__location__ " Failed to "
+                                     "find record with hash 0x%08x coming "
+                                     "back from RECEIVE_RECORDS "
+                                     "control in delete list.\n",
+                                     ctdb_hash(&reckey)));
+                               vdata->count.delete_list.local_error++;
+                               vdata->count.delete_list.left--;
                        }
 
-                       rec = (struct ctdb_rec_data *)(rec->length + (uint8_t *)rec);
+                       rec = (struct ctdb_rec_data_old *)(rec->length + (uint8_t *)rec);
                }
        }
 
-       if (vdata->delete_left == 0) {
+       if (vdata->count.delete_list.left == 0) {
                goto success;
        }
 
@@ -993,20 +1000,23 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                                 offsetof(struct ctdb_marshall_buffer, data));
        if (recs->records == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               ret = -1;
                goto done;
        }
        recs->records->db_id = ctdb_db->db_id;
 
-       trbt_traversearray32(vdata->delete_list, 1,
-                            delete_marshall_traverse, recs);
+       ret = trbt_traversearray32(vdata->delete_list, 1,
+                                  delete_marshall_traverse, recs);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, (__location__ " Error traversing the "
+                     "delete list for second marshalling.\n"));
+               goto done;
+       }
 
-       indata.dsize = talloc_get_size(recs->records);
-       indata.dptr  = (void *)recs->records;
+       indata = ctdb_marshall_finish(recs->records);
 
        for (i = 0; i < num_active_nodes; i++) {
                struct ctdb_marshall_buffer *records;
-               struct ctdb_rec_data *rec;
+               struct ctdb_rec_data_old *rec;
                int32_t res;
                TDB_DATA outdata;
 
@@ -1018,7 +1028,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                        DEBUG(DEBUG_ERR, ("Failed to delete records on "
                                          "node %u: ret[%d] res[%d]\n",
                                          active_nodes[i], ret, res));
-                       ret = -1;
                        goto done;
                }
 
@@ -1029,7 +1038,7 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                 * the list to delete locally.
                 */
                records = (struct ctdb_marshall_buffer *)outdata.dptr;
-               rec = (struct ctdb_rec_data *)&records->data[0];
+               rec = (struct ctdb_rec_data_old *)&records->data[0];
                while (records->count-- > 1) {
                        TDB_DATA reckey, recdata;
                        struct ctdb_ltdb_header *rechdr;
@@ -1042,7 +1051,6 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
 
                        if (recdata.dsize < sizeof(struct ctdb_ltdb_header)) {
                                DEBUG(DEBUG_CRIT,(__location__ " bad ltdb record\n"));
-                               ret = -1;
                                goto done;
                        }
                        rechdr = (struct ctdb_ltdb_header *)recdata.dptr;
@@ -1060,15 +1068,23 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
                                 * the tree and update statistics.
                                 */
                                talloc_free(dd);
-                               vdata->delete_remote_error++;
-                               vdata->delete_left--;
+                               vdata->count.delete_list.remote_error++;
+                               vdata->count.delete_list.left--;
+                       } else {
+                               DEBUG(DEBUG_ERR, (__location__ " Failed to "
+                                     "find record with hash 0x%08x coming "
+                                     "back from TRY_DELETE_RECORDS "
+                                     "control in delete list.\n",
+                                     ctdb_hash(&reckey)));
+                               vdata->count.delete_list.local_error++;
+                               vdata->count.delete_list.left--;
                        }
 
-                       rec = (struct ctdb_rec_data *)(rec->length + (uint8_t *)rec);
+                       rec = (struct ctdb_rec_data_old *)(rec->length + (uint8_t *)rec);
                }
        }
 
-       if (vdata->delete_left == 0) {
+       if (vdata->count.delete_list.left == 0) {
                goto success;
        }
 
@@ -1080,33 +1096,38 @@ static int ctdb_process_delete_list(struct ctdb_db_context *ctdb_db,
         * active remote nodes.
         */
 
-       trbt_traversearray32(vdata->delete_list, 1,
-                            delete_record_traverse, vdata);
+       ret = trbt_traversearray32(vdata->delete_list, 1,
+                                  delete_record_traverse, vdata);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, (__location__ " Error traversing the "
+                     "delete list for deletion.\n"));
+       }
 
 success:
 
-       if (vdata->delete_left != 0) {
+       if (vdata->count.delete_list.left != 0) {
                DEBUG(DEBUG_ERR, (__location__ " Vaccum db[%s] error: "
                      "there are %u records left for deletion after "
                      "processing delete list\n",
                      ctdb_db->db_name,
-                     (unsigned)vdata->delete_left));
+                     (unsigned)vdata->count.delete_list.left));
        }
 
-       sum = vdata->delete_deleted
-           + vdata->delete_skipped
-           + vdata->delete_remote_error
-           + vdata->delete_local_error
-           + vdata->delete_left;
+       sum = vdata->count.delete_list.deleted
+           + vdata->count.delete_list.skipped
+           + vdata->count.delete_list.remote_error
+           + vdata->count.delete_list.local_error
+           + vdata->count.delete_list.left;
 
-       if (vdata->delete_count != sum) {
+       if (vdata->count.delete_list.total != sum) {
                DEBUG(DEBUG_ERR, (__location__ " Inconsistency in vacuum "
                      "delete list counts for db[%s]: total[%u] != sum[%u]\n",
-                     ctdb_db->db_name, (unsigned)vdata->delete_count,
+                     ctdb_db->db_name,
+                     (unsigned)vdata->count.delete_list.total,
                      (unsigned)sum));
        }
 
-       if (vdata->delete_count > 0) {
+       if (vdata->count.delete_list.total > 0) {
                DEBUG(DEBUG_INFO,
                      (__location__
                       " vacuum delete list statistics: "
@@ -1118,47 +1139,63 @@ success:
                       "loc.err[%u] "
                       "left[%u]\n",
                       ctdb_db->db_name,
-                      (unsigned)vdata->delete_count,
-                      (unsigned)vdata->delete_deleted,
-                      (unsigned)vdata->delete_skipped,
-                      (unsigned)vdata->delete_remote_error,
-                      (unsigned)vdata->delete_local_error,
-                      (unsigned)vdata->delete_left));
+                      (unsigned)vdata->count.delete_list.total,
+                      (unsigned)vdata->count.delete_list.deleted,
+                      (unsigned)vdata->count.delete_list.skipped,
+                      (unsigned)vdata->count.delete_list.remote_error,
+                      (unsigned)vdata->count.delete_list.local_error,
+                      (unsigned)vdata->count.delete_list.left));
        }
 
-       ret = 0;
-
 done:
        talloc_free(tmp_ctx);
 
-       return ret;
+       return;
 }
 
 /**
  * initialize the vacuum_data
  */
-static int ctdb_vacuum_init_vacuum_data(struct ctdb_db_context *ctdb_db,
-                                       struct vacuum_data *vdata)
+static struct vacuum_data *ctdb_vacuum_init_vacuum_data(
+                                       struct ctdb_db_context *ctdb_db,
+                                       TALLOC_CTX *mem_ctx)
 {
        int i;
        struct ctdb_context *ctdb = ctdb_db->ctdb;
+       struct vacuum_data *vdata;
 
-       vdata->fast_added_to_delete_list = 0;
-       vdata->fast_added_to_vacuum_fetch_list = 0;
-       vdata->fast_deleted = 0;
-       vdata->fast_skipped = 0;
-       vdata->fast_error = 0;
-       vdata->fast_total = 0;
-       vdata->full_scheduled = 0;
-       vdata->full_skipped = 0;
-       vdata->full_error = 0;
-       vdata->full_total = 0;
-       vdata->delete_count = 0;
-       vdata->delete_left = 0;
-       vdata->delete_remote_error = 0;
-       vdata->delete_local_error = 0;
-       vdata->delete_skipped = 0;
-       vdata->delete_deleted = 0;
+       vdata = talloc_zero(mem_ctx, struct vacuum_data);
+       if (vdata == NULL) {
+               DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
+               return NULL;
+       }
+
+       vdata->ctdb = ctdb_db->ctdb;
+       vdata->ctdb_db = ctdb_db;
+       vdata->delete_list = trbt_create(vdata, 0);
+       if (vdata->delete_list == NULL) {
+               DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
+               goto fail;
+       }
+
+       vdata->start = timeval_current();
+
+       vdata->count.delete_queue.added_to_delete_list = 0;
+       vdata->count.delete_queue.added_to_vacuum_fetch_list = 0;
+       vdata->count.delete_queue.deleted = 0;
+       vdata->count.delete_queue.skipped = 0;
+       vdata->count.delete_queue.error = 0;
+       vdata->count.delete_queue.total = 0;
+       vdata->count.db_traverse.scheduled = 0;
+       vdata->count.db_traverse.skipped = 0;
+       vdata->count.db_traverse.error = 0;
+       vdata->count.db_traverse.total = 0;
+       vdata->count.delete_list.total = 0;
+       vdata->count.delete_list.left = 0;
+       vdata->count.delete_list.remote_error = 0;
+       vdata->count.delete_list.local_error = 0;
+       vdata->count.delete_list.skipped = 0;
+       vdata->count.delete_list.deleted = 0;
 
        /* the list needs to be of length num_nodes */
        vdata->vacuum_fetch_list = talloc_zero_array(vdata,
@@ -1166,7 +1203,7 @@ static int ctdb_vacuum_init_vacuum_data(struct ctdb_db_context *ctdb_db,
                                                ctdb->num_nodes);
        if (vdata->vacuum_fetch_list == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               return -1;
+               goto fail;
        }
        for (i = 0; i < ctdb->num_nodes; i++) {
                vdata->vacuum_fetch_list[i] = (struct ctdb_marshall_buffer *)
@@ -1174,12 +1211,17 @@ static int ctdb_vacuum_init_vacuum_data(struct ctdb_db_context *ctdb_db,
                                         offsetof(struct ctdb_marshall_buffer, data));
                if (vdata->vacuum_fetch_list[i] == NULL) {
                        DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-                       return -1;
+                       talloc_free(vdata);
+                       return NULL;
                }
                vdata->vacuum_fetch_list[i]->db_id = ctdb_db->db_id;
        }
 
-       return 0;
+       return vdata;
+
+fail:
+       talloc_free(vdata);
+       return NULL;
 }
 
 /**
@@ -1215,11 +1257,12 @@ static int ctdb_vacuum_init_vacuum_data(struct ctdb_db_context *ctdb_db,
  * This executes in the child context.
  */
 static int ctdb_vacuum_db(struct ctdb_db_context *ctdb_db,
-                         struct vacuum_data *vdata,
                          bool full_vacuum_run)
 {
        struct ctdb_context *ctdb = ctdb_db->ctdb;
        int ret, pnn;
+       struct vacuum_data *vdata;
+       TALLOC_CTX *tmp_ctx;
 
        DEBUG(DEBUG_INFO, (__location__ " Entering %s vacuum run for db "
                           "%s db_id[0x%08x]\n",
@@ -1240,159 +1283,32 @@ static int ctdb_vacuum_db(struct ctdb_db_context *ctdb_db,
 
        ctdb->pnn = pnn;
 
-       ret = ctdb_vacuum_init_vacuum_data(ctdb_db, vdata);
-       if (ret != 0) {
-               return ret;
-       }
-
-       if (full_vacuum_run) {
-               ret = ctdb_vacuum_traverse_db(ctdb_db, vdata);
-               if (ret != 0) {
-                       return ret;
-               }
-       }
-
-       ctdb_process_delete_queue(ctdb_db, vdata);
-
-       ret = ctdb_process_vacuum_fetch_lists(ctdb_db, vdata);
-       if (ret != 0) {
-               return ret;
-       }
-
-       ret = ctdb_process_delete_list(ctdb_db, vdata);
-       if (ret != 0) {
-               return ret;
-       }
-
-       /* this ensures we run our event queue */
-       ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
-
-       return 0;
-}
-
-
-/*
- * traverse function for repacking
- */
-static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
-                          void *private_data)
-{
-       struct vacuum_data *vdata = (struct vacuum_data *)private_data;
-
-       if (vdata->vacuum) {
-               uint32_t hash = ctdb_hash(&key);
-               struct delete_record_data *kd;
-               /*
-                * check if we can ignore this record because it's in the delete_list
-                */
-               kd = (struct delete_record_data *)trbt_lookup32(vdata->delete_list, hash);
-               /*
-                * there might be hash collisions so we have to compare the keys here to be sure
-                */
-               if (kd && kd->key.dsize == key.dsize && memcmp(kd->key.dptr, key.dptr, key.dsize) == 0) {
-                       struct ctdb_ltdb_header *hdr = (struct ctdb_ltdb_header *)data.dptr;
-                       /*
-                        * we have to check if the record hasn't changed in the meantime in order to
-                        * savely remove it from the database
-                        */
-                       if (data.dsize == sizeof(struct ctdb_ltdb_header) &&
-                               hdr->dmaster == kd->ctdb->pnn &&
-                               ctdb_lmaster(kd->ctdb, &(kd->key)) == kd->ctdb->pnn &&
-                               kd->hdr.rsn == hdr->rsn) {
-                               vdata->vacuumed++;
-                               return 0;
-                       }
-               }
-       }
-       if (tdb_store(vdata->dest_db, key, data, TDB_INSERT) != 0) {
-               vdata->traverse_error = true;
-               return -1;
-       }
-       vdata->copied++;
-       return 0;
-}
-
-/*
- * repack a tdb
- */
-static int ctdb_repack_tdb(struct tdb_context *tdb, TALLOC_CTX *mem_ctx, struct vacuum_data *vdata)
-{
-       struct tdb_context *tmp_db;
-
-       if (tdb_transaction_start(tdb) != 0) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to start transaction\n"));
-               return -1;
-       }
-
-       tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb),
-                         TDB_INTERNAL|TDB_DISALLOW_NESTING,
-                         O_RDWR|O_CREAT, 0);
-       if (tmp_db == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to create tmp_db\n"));
-               tdb_transaction_cancel(tdb);
+       tmp_ctx = talloc_new(ctdb_db);
+       if (tmp_ctx == NULL) {
+               DEBUG(DEBUG_ERR, ("Out of memory!\n"));
                return -1;
        }
 
-       vdata->traverse_error = false;
-       vdata->dest_db = tmp_db;
-       vdata->vacuum = true;
-       vdata->vacuumed = 0;
-       vdata->copied = 0;
-
-       /*
-        * repack and vacuum on-the-fly by not writing the records that are
-        * no longer needed
-        */
-       if (tdb_traverse_read(tdb, repack_traverse, vdata) == -1) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to traverse copying out\n"));
-               tdb_transaction_cancel(tdb);
-               tdb_close(tmp_db);
-               return -1;              
-       }
-
-       DEBUG(DEBUG_INFO,(__location__ " %u records vacuumed\n", vdata->vacuumed));
-       
-       if (vdata->traverse_error) {
-               DEBUG(DEBUG_ERR,(__location__ " Error during traversal\n"));
-               tdb_transaction_cancel(tdb);
-               tdb_close(tmp_db);
+       vdata = ctdb_vacuum_init_vacuum_data(ctdb_db, tmp_ctx);
+       if (vdata == NULL) {
+               talloc_free(tmp_ctx);
                return -1;
        }
 
-       if (tdb_wipe_all(tdb) != 0) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to wipe database\n"));
-               tdb_transaction_cancel(tdb);
-               tdb_close(tmp_db);
-               return -1;
+       if (full_vacuum_run) {
+               ctdb_vacuum_traverse_db(ctdb_db, vdata);
        }
 
-       vdata->traverse_error = false;
-       vdata->dest_db = tdb;
-       vdata->vacuum = false;
-       vdata->copied = 0;
-
-       if (tdb_traverse_read(tmp_db, repack_traverse, vdata) == -1) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to traverse copying back\n"));
-               tdb_transaction_cancel(tdb);
-               tdb_close(tmp_db);
-               return -1;              
-       }
+       ctdb_process_delete_queue(ctdb_db, vdata);
 
-       if (vdata->traverse_error) {
-               DEBUG(DEBUG_ERR,(__location__ " Error during second traversal\n"));
-               tdb_transaction_cancel(tdb);
-               tdb_close(tmp_db);
-               return -1;
-       }
+       ctdb_process_vacuum_fetch_lists(ctdb_db, vdata);
 
-       tdb_close(tmp_db);
+       ctdb_process_delete_list(ctdb_db, vdata);
 
+       talloc_free(tmp_ctx);
 
-       if (tdb_transaction_commit(tdb) != 0) {
-               DEBUG(DEBUG_ERR,(__location__ " Failed to commit\n"));
-               return -1;
-       }
-       DEBUG(DEBUG_INFO,(__location__ " %u records copied\n", vdata->copied));
+       /* this ensures we run our event queue */
+       ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
 
        return 0;
 }
@@ -1402,46 +1318,21 @@ static int ctdb_repack_tdb(struct tdb_context *tdb, TALLOC_CTX *mem_ctx, struct
  * called from the child context
  */
 static int ctdb_vacuum_and_repack_db(struct ctdb_db_context *ctdb_db,
-                                    TALLOC_CTX *mem_ctx,
                                     bool full_vacuum_run)
 {
        uint32_t repack_limit = ctdb_db->ctdb->tunable.repack_limit;
        const char *name = ctdb_db->db_name;
        int freelist_size = 0;
-       struct vacuum_data *vdata;
-
-       vdata = talloc_zero(mem_ctx, struct vacuum_data);
-       if (vdata == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               return -1;
-       }
-
-       vdata->ctdb = ctdb_db->ctdb;
-       vdata->repack_limit = repack_limit;
-       vdata->delete_list = trbt_create(vdata, 0);
-       vdata->ctdb_db = ctdb_db;
-       if (vdata->delete_list == NULL) {
-               DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
-               talloc_free(vdata);
-               return -1;
-       }
+       int ret;
 
-       vdata->start = timeval_current();
-       /*
-        * gather all records that can be deleted in vdata
-        */
-       if (ctdb_vacuum_db(ctdb_db, vdata, full_vacuum_run) != 0) {
+       if (ctdb_vacuum_db(ctdb_db, full_vacuum_run) != 0) {
                DEBUG(DEBUG_ERR,(__location__ " Failed to vacuum '%s'\n", name));
        }
 
-       if (repack_limit != 0) {
-               freelist_size = tdb_freelist_size(ctdb_db->ltdb->tdb);
-               if (freelist_size == -1) {
-                       DEBUG(DEBUG_ERR,(__location__ " Failed to get freelist size for '%s'\n", name));
-                       talloc_free(vdata);
-                       return -1;
-               }
+       freelist_size = tdb_freelist_size(ctdb_db->ltdb->tdb);
+       if (freelist_size == -1) {
+               DEBUG(DEBUG_ERR,(__location__ " Failed to get freelist size for '%s'\n", name));
+               return -1;
        }
 
        /*
@@ -1449,22 +1340,17 @@ static int ctdb_vacuum_and_repack_db(struct ctdb_db_context *ctdb_db,
         */
        if ((repack_limit == 0 || (uint32_t)freelist_size < repack_limit))
        {
-               talloc_free(vdata);
                return 0;
        }
 
-       DEBUG(DEBUG_INFO,("Repacking %s with %u freelist entries and %u records to delete\n", 
-                       name, freelist_size, vdata->delete_left));
+       DEBUG(DEBUG_INFO, ("Repacking %s with %u freelist entries\n",
+                          name, freelist_size));
 
-       /*
-        * repack and implicitely get rid of the records we can delete
-        */
-       if (ctdb_repack_tdb(ctdb_db->ltdb->tdb, mem_ctx, vdata) != 0) {
+       ret = tdb_repack(ctdb_db->ltdb->tdb);
+       if (ret != 0) {
                DEBUG(DEBUG_ERR,(__location__ " Failed to repack '%s'\n", name));
-               talloc_free(vdata);
                return -1;
        }
-       talloc_free(vdata);
 
        return 0;
 }
@@ -1482,6 +1368,7 @@ static int vacuum_child_destructor(struct ctdb_vacuum_child_context *child_ctx)
        struct ctdb_db_context *ctdb_db = child_ctx->vacuum_handle->ctdb_db;
        struct ctdb_context *ctdb = ctdb_db->ctdb;
 
+       CTDB_UPDATE_DB_LATENCY(ctdb_db, "vacuum", vacuum.latency, l);
        DEBUG(DEBUG_INFO,("Vacuuming took %.3f seconds for database %s\n", l, ctdb_db->db_name));
 
        if (child_ctx->child_pid != -1) {
@@ -1493,9 +1380,9 @@ static int vacuum_child_destructor(struct ctdb_vacuum_child_context *child_ctx)
 
        DLIST_REMOVE(ctdb->vacuumers, child_ctx);
 
-       event_add_timed(ctdb->ev, child_ctx->vacuum_handle,
-                       timeval_current_ofs(get_vacuum_interval(ctdb_db), 0), 
-                       ctdb_vacuum_event, child_ctx->vacuum_handle);
+       tevent_add_timer(ctdb->ev, child_ctx->vacuum_handle,
+                        timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
+                        ctdb_vacuum_event, child_ctx->vacuum_handle);
 
        return 0;
 }
@@ -1503,8 +1390,9 @@ static int vacuum_child_destructor(struct ctdb_vacuum_child_context *child_ctx)
 /*
  * this event is generated when a vacuum child process times out
  */
-static void vacuum_child_timeout(struct event_context *ev, struct timed_event *te,
-                                        struct timeval t, void *private_data)
+static void vacuum_child_timeout(struct tevent_context *ev,
+                                struct tevent_timer *te,
+                                struct timeval t, void *private_data)
 {
        struct ctdb_vacuum_child_context *child_ctx = talloc_get_type(private_data, struct ctdb_vacuum_child_context);
 
@@ -1519,8 +1407,9 @@ static void vacuum_child_timeout(struct event_context *ev, struct timed_event *t
 /*
  * this event is generated when a vacuum child process has completed
  */
-static void vacuum_child_handler(struct event_context *ev, struct fd_event *fde,
-                            uint16_t flags, void *private_data)
+static void vacuum_child_handler(struct tevent_context *ev,
+                                struct tevent_fd *fde,
+                                uint16_t flags, void *private_data)
 {
        struct ctdb_vacuum_child_context *child_ctx = talloc_get_type(private_data, struct ctdb_vacuum_child_context);
        char c = 0;
@@ -1529,7 +1418,7 @@ static void vacuum_child_handler(struct event_context *ev, struct fd_event *fde,
        DEBUG(DEBUG_INFO,("Vacuuming child process %d finished for db %s\n", child_ctx->child_pid, child_ctx->vacuum_handle->ctdb_db->db_name));
        child_ctx->child_pid = -1;
 
-       ret = read(child_ctx->fd[0], &c, 1);
+       ret = sys_read(child_ctx->fd[0], &c, 1);
        if (ret != 1 || c != 0) {
                child_ctx->status = VACUUM_ERROR;
                DEBUG(DEBUG_ERR, ("A vacuum child process failed with an error for database %s. ret=%d c=%d\n", child_ctx->vacuum_handle->ctdb_db->db_name, ret, c));
@@ -1543,9 +1432,9 @@ static void vacuum_child_handler(struct event_context *ev, struct fd_event *fde,
 /*
  * this event is called every time we need to start a new vacuum process
  */
-static void
-ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
-                              struct timeval t, void *private_data)
+static void ctdb_vacuum_event(struct tevent_context *ev,
+                             struct tevent_timer *te,
+                             struct timeval t, void *private_data)
 {
        struct ctdb_vacuum_handle *vacuum_handle = talloc_get_type(private_data, struct ctdb_vacuum_handle);
        struct ctdb_db_context *ctdb_db = vacuum_handle->ctdb_db;
@@ -1554,7 +1443,7 @@ ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
        struct tevent_fd *fde;
        int ret;
 
-       /* we dont vacuum if we are in recovery mode, or db frozen */
+       /* we don't vacuum if we are in recovery mode, or db frozen */
        if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE ||
            ctdb->freeze_mode[ctdb_db->priority] != CTDB_FREEZE_NONE) {
                DEBUG(DEBUG_INFO, ("Not vacuuming %s (%s)\n", ctdb_db->db_name,
@@ -1562,9 +1451,20 @@ ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
                                   : ctdb->freeze_mode[ctdb_db->priority] == CTDB_FREEZE_PENDING
                                   ? "freeze pending"
                                   : "frozen"));
-               event_add_timed(ctdb->ev, vacuum_handle,
-                       timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
-                       ctdb_vacuum_event, vacuum_handle);
+               tevent_add_timer(ctdb->ev, vacuum_handle,
+                                timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
+                                ctdb_vacuum_event, vacuum_handle);
+               return;
+       }
+
+       /* Do not allow multiple vacuuming child processes to be active at the
+        * same time.  If there is vacuuming child process active, delay
+        * new vacuuming event to stagger vacuuming events.
+        */
+       if (ctdb->vacuumers != NULL) {
+               tevent_add_timer(ctdb->ev, vacuum_handle,
+                                timeval_current_ofs(0, 500*1000),
+                                ctdb_vacuum_event, vacuum_handle);
                return;
        }
 
@@ -1579,9 +1479,9 @@ ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
        if (ret != 0) {
                talloc_free(child_ctx);
                DEBUG(DEBUG_ERR, ("Failed to create pipe for vacuum child process.\n"));
-               event_add_timed(ctdb->ev, vacuum_handle,
-                       timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
-                       ctdb_vacuum_event, vacuum_handle);
+               tevent_add_timer(ctdb->ev, vacuum_handle,
+                                timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
+                                ctdb_vacuum_event, vacuum_handle);
                return;
        }
 
@@ -1595,9 +1495,9 @@ ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
                close(child_ctx->fd[1]);
                talloc_free(child_ctx);
                DEBUG(DEBUG_ERR, ("Failed to fork vacuum child process.\n"));
-               event_add_timed(ctdb->ev, vacuum_handle,
-                       timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
-                       ctdb_vacuum_event, vacuum_handle);
+               tevent_add_timer(ctdb->ev, vacuum_handle,
+                                timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
+                                ctdb_vacuum_event, vacuum_handle);
                return;
        }
 
@@ -1608,24 +1508,20 @@ ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
                close(child_ctx->fd[0]);
 
                DEBUG(DEBUG_INFO,("Vacuuming child process %d for db %s started\n", getpid(), ctdb_db->db_name));
-               ctdb_set_process_name("ctdb_vacuum");
+               prctl_set_comment("ctdb_vacuum");
                if (switch_from_server_to_client(ctdb, "vacuum-%s", ctdb_db->db_name) != 0) {
                        DEBUG(DEBUG_CRIT, (__location__ "ERROR: failed to switch vacuum daemon into client mode. Shutting down.\n"));
                        _exit(1);
                }
 
-               /* 
-                * repack the db
-                */
                if ((ctdb->tunable.vacuum_fast_path_count > 0) &&
                    (vacuum_handle->fast_path_count == 0))
                {
                        full_vacuum_run = true;
                }
-               cc = ctdb_vacuum_and_repack_db(ctdb_db, child_ctx,
-                                              full_vacuum_run);
+               cc = ctdb_vacuum_and_repack_db(ctdb_db, full_vacuum_run);
 
-               write(child_ctx->fd[1], &cc, 1);
+               sys_write(child_ctx->fd[1], &cc, 1);
                _exit(0);
        }
 
@@ -1649,14 +1545,14 @@ ctdb_vacuum_event(struct event_context *ev, struct timed_event *te,
                                 "in parent context. Shutting down\n");
        }
 
-       event_add_timed(ctdb->ev, child_ctx,
-               timeval_current_ofs(ctdb->tunable.vacuum_max_run_time, 0),
-               vacuum_child_timeout, child_ctx);
+       tevent_add_timer(ctdb->ev, child_ctx,
+                        timeval_current_ofs(ctdb->tunable.vacuum_max_run_time, 0),
+                        vacuum_child_timeout, child_ctx);
 
        DEBUG(DEBUG_DEBUG, (__location__ " Created PIPE FD:%d to child vacuum process\n", child_ctx->fd[0]));
 
-       fde = event_add_fd(ctdb->ev, child_ctx, child_ctx->fd[0],
-                          EVENT_FD_READ, vacuum_child_handler, child_ctx);
+       fde = tevent_add_fd(ctdb->ev, child_ctx, child_ctx->fd[0],
+                           TEVENT_FD_READ, vacuum_child_handler, child_ctx);
        tevent_fd_set_auto_close(fde);
 
        vacuum_handle->child_ctx = child_ctx;
@@ -1691,9 +1587,9 @@ int ctdb_vacuum_init(struct ctdb_db_context *ctdb_db)
        ctdb_db->vacuum_handle->ctdb_db         = ctdb_db;
        ctdb_db->vacuum_handle->fast_path_count = 0;
 
-       event_add_timed(ctdb_db->ctdb->ev, ctdb_db->vacuum_handle, 
-                       timeval_current_ofs(get_vacuum_interval(ctdb_db), 0), 
-                       ctdb_vacuum_event, ctdb_db->vacuum_handle);
+       tevent_add_timer(ctdb_db->ctdb->ev, ctdb_db->vacuum_handle,
+                        timeval_current_ofs(get_vacuum_interval(ctdb_db), 0),
+                        ctdb_vacuum_event, ctdb_db->vacuum_handle);
 
        return 0;
 }
@@ -1763,11 +1659,11 @@ static int insert_record_into_delete_queue(struct ctdb_db_context *ctdb_db,
 
        hash = (uint32_t)ctdb_hash(&key);
 
-       DEBUG(DEBUG_INFO, (__location__ " schedule for deletion: db[%s] "
-                          "db_id[0x%08x] "
-                          "key_hash[0x%08x] "
-                          "lmaster[%u] "
-                          "migrated_with_data[%s]\n",
+       DEBUG(DEBUG_DEBUG, (__location__ " schedule for deletion: db[%s] "
+                           "db_id[0x%08x] "
+                           "key_hash[0x%08x] "
+                           "lmaster[%u] "
+                           "migrated_with_data[%s]\n",
                            ctdb_db->db_name, ctdb_db->db_id,
                            hash,
                            ctdb_lmaster(ctdb_db->ctdb, &key),
@@ -1850,7 +1746,7 @@ int32_t ctdb_local_schedule_for_deletion(struct ctdb_db_context *ctdb_db,
                return ret;
        }
 
-       /* if we dont have a connection to the daemon we can not send
+       /* if we don't have a connection to the daemon we can not send
           a control. For example sometimes from update_record control child
           process.
        */