summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ctdb/include/ctdb_private.h13
-rw-r--r--ctdb/server/ctdb_control.c9
-rw-r--r--ctdb/server/ctdb_vacuum.c64
3 files changed, 86 insertions, 0 deletions
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index ede1df8552..b16ed74981 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -1385,4 +1385,17 @@ int ctdb_deferred_drop_all_ips(struct ctdb_context *ctdb);
int ctdb_process_deferred_attach(struct ctdb_context *ctdb);
+/**
+ * structure to pass to a schedule_for_deletion_control
+ */
+struct ctdb_control_schedule_for_deletion {
+ uint32_t db_id;
+ struct ctdb_ltdb_header hdr;
+ uint32_t keylen;
+ uint8_t key[1]; /* key[] */
+};
+
+int32_t ctdb_control_schedule_for_deletion(struct ctdb_context *ctdb,
+ TDB_DATA indata);
+
#endif
diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c
index 69724e3965..748907f2a9 100644
--- a/ctdb/server/ctdb_control.c
+++ b/ctdb/server/ctdb_control.c
@@ -604,6 +604,15 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
CHECK_CONTROL_DATA_SIZE(0);
return ctdb_control_get_stat_history(ctdb, c, outdata);
+ case CTDB_CONTROL_SCHEDULE_FOR_DELETION: {
+ struct ctdb_control_schedule_for_deletion *d;
+ size_t size = offsetof(struct ctdb_control_schedule_for_deletion, key);
+ CHECK_CONTROL_MIN_DATA_SIZE(size);
+ d = (struct ctdb_control_schedule_for_deletion *)indata.dptr;
+ size += d->keylen;
+ CHECK_CONTROL_DATA_SIZE(size);
+ return ctdb_control_schedule_for_deletion(ctdb, indata);
+ }
default:
DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
return -1;
diff --git a/ctdb/server/ctdb_vacuum.c b/ctdb/server/ctdb_vacuum.c
index 94d3416bf3..ec3b5f29f2 100644
--- a/ctdb/server/ctdb_vacuum.c
+++ b/ctdb/server/ctdb_vacuum.c
@@ -1269,3 +1269,67 @@ int ctdb_vacuum_init(struct ctdb_db_context *ctdb_db)
return 0;
}
+
+/**
+ * Schedule a record for deletetion.
+ * Called from the parent context.
+ */
+int32_t ctdb_control_schedule_for_deletion(struct ctdb_context *ctdb,
+ TDB_DATA indata)
+{
+ struct ctdb_control_schedule_for_deletion *dd;
+ struct ctdb_db_context *ctdb_db;
+ int ret;
+ TDB_DATA key;
+ uint32_t hash;
+ struct delete_record_data *kd;
+
+ dd = (struct ctdb_control_schedule_for_deletion *)indata.dptr;
+
+ ctdb_db = find_ctdb_db(ctdb, dd->db_id);
+ if (ctdb_db == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " Unknown db id 0x%08x\n",
+ dd->db_id));
+ return -1;
+ }
+
+ key.dsize = dd->keylen;
+ key.dptr = dd->key;
+
+ 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",
+ ctdb_db->db_name, dd->db_id,
+ hash,
+ ctdb_lmaster(ctdb_db->ctdb, &key),
+ dd->hdr.flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA ? "yes" : "no"));
+
+ kd = (struct delete_record_data *)trbt_lookup32(ctdb_db->delete_queue, hash);
+ if (kd != NULL) {
+ if ((kd->key.dsize != key.dsize) ||
+ (memcmp(kd->key.dptr, key.dptr, key.dsize) != 0))
+ {
+ DEBUG(DEBUG_INFO,
+ ("schedule for deletion: Hash collision (0x%08x)."
+ " Skipping the record.\n", hash));
+ return 0;
+ } else {
+ DEBUG(DEBUG_INFO,
+ ("schedule for deletetion: Overwriting entry for "
+ "key with hash 0x%08x.\n", hash));
+ }
+ }
+
+ ret = insert_delete_record_data_into_tree(ctdb, ctdb_db,
+ ctdb_db->delete_queue,
+ &dd->hdr, key);
+ if (ret != 0) {
+ return -1;
+ }
+
+ return 0;
+}