summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ctdb/include/ctdb_private.h5
-rw-r--r--ctdb/server/ctdb_call.c93
2 files changed, 98 insertions, 0 deletions
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index f7ab821b166..9709d67f35c 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -517,6 +517,7 @@ struct ctdb_db_context {
int pending_requests;
struct lockwait_handle *lockwait_active;
struct lockwait_handle *lockwait_overflow;
+ struct revokechild_handle *revokechild_active;
struct ctdb_persistent_state *persistent_state;
struct trbt_tree *delete_queue;
int (*ctdb_ltdb_store_fn)(struct ctdb_db_context *ctdb_db,
@@ -1451,4 +1452,8 @@ typedef void (*ctdb_trackingdb_cb)(struct ctdb_context *ctdb, uint32_t pnn, void
void ctdb_trackingdb_traverse(struct ctdb_context *ctdb, TDB_DATA data, ctdb_trackingdb_cb cb, void *private_data);
+typedef void (*deferred_requeue_fn)(void *call_context, struct ctdb_req_header *hdr);
+
+int ctdb_add_revoke_deferred_call(struct ctdb_context *ctdb, struct ctdb_db_context *ctdb_db, TDB_DATA key, struct ctdb_req_header *hdr, deferred_requeue_fn fn, void *call_context);
+
#endif
diff --git a/ctdb/server/ctdb_call.c b/ctdb/server/ctdb_call.c
index eb5e2582b9c..8d79de1fc7b 100644
--- a/ctdb/server/ctdb_call.c
+++ b/ctdb/server/ctdb_call.c
@@ -894,3 +894,96 @@ void ctdb_send_keepalive(struct ctdb_context *ctdb, uint32_t destnode)
talloc_free(r);
}
+
+
+
+struct revokechild_deferred_call {
+ struct ctdb_context *ctdb;
+ struct ctdb_req_header *hdr;
+ deferred_requeue_fn fn;
+ void *ctx;
+};
+
+struct revokechild_handle {
+ struct revokechild_handle *next, *prev;
+ struct ctdb_context *ctdb;
+ struct ctdb_db_context *ctdb_db;
+ struct fd_event *fde;
+ int status;
+ int fd[2];
+ pid_t child;
+ TDB_DATA key;
+};
+
+struct revokechild_requeue_handle {
+ struct ctdb_context *ctdb;
+ struct ctdb_req_header *hdr;
+ deferred_requeue_fn fn;
+ void *ctx;
+};
+
+static void deferred_call_requeue(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private_data)
+{
+ struct revokechild_requeue_handle *requeue_handle = talloc_get_type(private_data, struct revokechild_requeue_handle);
+
+ requeue_handle->fn(requeue_handle->ctx, requeue_handle->hdr);
+ talloc_free(requeue_handle);
+}
+
+static int deferred_call_destructor(struct revokechild_deferred_call *deferred_call)
+{
+ struct ctdb_context *ctdb = deferred_call->ctdb;
+ struct revokechild_requeue_handle *requeue_handle = talloc(ctdb, struct revokechild_requeue_handle);
+ struct ctdb_req_call *c = (struct ctdb_req_call *)deferred_call->hdr;
+
+ requeue_handle->ctdb = ctdb;
+ requeue_handle->hdr = deferred_call->hdr;
+ requeue_handle->fn = deferred_call->fn;
+ requeue_handle->ctx = deferred_call->ctx;
+ talloc_steal(requeue_handle, requeue_handle->hdr);
+
+ /* when revoking, any READONLY requests have 1 second grace to let read/write finish first */
+ event_add_timed(ctdb->ev, requeue_handle, timeval_current_ofs(0, 0), deferred_call_requeue, requeue_handle);
+
+ return 0;
+}
+
+int ctdb_add_revoke_deferred_call(struct ctdb_context *ctdb, struct ctdb_db_context *ctdb_db, TDB_DATA key, struct ctdb_req_header *hdr, deferred_requeue_fn fn, void *call_context)
+{
+ struct revokechild_handle *rc;
+ struct revokechild_deferred_call *deferred_call;
+
+ for (rc = ctdb_db->revokechild_active; rc; rc = rc->next) {
+ if (rc->key.dsize == 0) {
+ continue;
+ }
+ if (rc->key.dsize != key.dsize) {
+ continue;
+ }
+ if (!memcmp(rc->key.dptr, key.dptr, key.dsize)) {
+ break;
+ }
+ }
+
+ if (rc == NULL) {
+ DEBUG(DEBUG_ERR,("Failed to add deferred call to revoke list. revoke structure not found\n"));
+ return -1;
+ }
+
+ deferred_call = talloc(rc, struct revokechild_deferred_call);
+ if (deferred_call == NULL) {
+ DEBUG(DEBUG_ERR,("Failed to allocate deferred call structure for revoking record\n"));
+ return -1;
+ }
+
+ deferred_call->ctdb = ctdb;
+ deferred_call->hdr = hdr;
+ deferred_call->fn = fn;
+ deferred_call->ctx = call_context;
+
+ talloc_set_destructor(deferred_call, deferred_call_destructor);
+ talloc_steal(deferred_call, hdr);
+
+ return 0;
+}