diff --git a/ctdb/client/ctdb_client.c b/ctdb/client/ctdb_client.c index 65fb10ec0c8..ecbe57e342b 100644 --- a/ctdb/client/ctdb_client.c +++ b/ctdb/client/ctdb_client.c @@ -665,22 +665,6 @@ int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, } -struct ctdb_client_control_state { - struct ctdb_context *ctdb; - uint32_t reqid; - int32_t status; - TDB_DATA outdata; - enum control_state state; - char *errormsg; - struct ctdb_req_control *c; - - /* if we have a callback registered for the completion (or failure) of - this control - if a callback is used, it MUST talloc_free the cb_data passed to it - */ - control_callback callback; - void *cb_private; -}; /* called when a control completes or timesout to invoke the callback @@ -690,10 +674,7 @@ static void invoke_control_callback(struct event_context *ev, struct timed_event struct timeval t, void *private_data) { struct ctdb_client_control_state *state; - struct ctdb_control_cb_data *cb_data; struct ctdb_context *ctdb; - control_callback callback; - void *cb_private; TALLOC_CTX *tmp_ctx = talloc_new(NULL); int ret; @@ -701,29 +682,12 @@ static void invoke_control_callback(struct event_context *ev, struct timed_event talloc_steal(tmp_ctx, state); ctdb = state->ctdb; - callback = state->callback; - cb_private = state->cb_private; - cb_data = talloc_zero(tmp_ctx, struct ctdb_control_cb_data); - if (cb_data == NULL) { - talloc_free(tmp_ctx); - CTDB_NO_MEMORY_VOID(ctdb, cb_data); - } + ret = ctdb_control_recv(ctdb, state, state, + &state->outdata, + &state->status, + &state->errormsg); - cb_data->state = state->state; - cb_data->vnn = state->c->hdr.destnode; - - ret = ctdb_control_recv(ctdb, state, cb_data, - &cb_data->outdata, - &cb_data->status, - &cb_data->errormsg); - /* we dont check ret since we expect that ctdb_control_recv can fail - for example if the control timedout - - state is always talloc_free()'d inside ctdb_control_recv - */ - - callback(cb_data, cb_private); talloc_free(tmp_ctx); } @@ -770,7 +734,7 @@ static void ctdb_client_reply_control(struct ctdb_context *ctdb, /* if we had a callback registered for this control, pull the response and call the callback. */ - if (state->callback) { + if (state->async.fn) { event_add_timed(ctdb->ev, state, timeval_zero(), invoke_control_callback, state); } } @@ -799,7 +763,7 @@ static void control_timeout_func(struct event_context *ev, struct timed_event *t /* if we had a callback registered for this control, pull the response and call the callback. */ - if (state->callback) { + if (state->async.fn) { event_add_timed(state->ctdb->ev, state, timeval_zero(), invoke_control_callback, state); } } @@ -810,8 +774,7 @@ struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb, uint32_t opcode, uint32_t flags, TDB_DATA data, TALLOC_CTX *mem_ctx, TDB_DATA *outdata, struct timeval *timeout, - char **errormsg, - control_callback callback, void *cb_private) + char **errormsg) { struct ctdb_client_control_state *state; size_t len; @@ -834,8 +797,6 @@ struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb, state->reqid = ctdb_reqid_new(ctdb, state); state->state = CTDB_CONTROL_WAIT; state->errormsg = NULL; - state->callback = callback; - state->cb_private = cb_private; talloc_set_destructor(state, ctdb_control_destructor); @@ -892,8 +853,12 @@ int ctdb_control_recv(struct ctdb_context *ctdb, while (state->state == CTDB_CONTROL_WAIT) { event_loop_once(ctdb->ev); } + if (state->state != CTDB_CONTROL_DONE) { DEBUG(0,(__location__ " ctdb_control_recv failed\n")); + if (state->async.fn) { + state->async.fn(state); + } talloc_free(state); return -1; } @@ -903,11 +868,13 @@ int ctdb_control_recv(struct ctdb_context *ctdb, if (errormsg) { (*errormsg) = talloc_move(mem_ctx, &state->errormsg); } + if (state->async.fn) { + state->async.fn(state); + } talloc_free(state); return -1; } - if (outdata) { *outdata = state->outdata; outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize); @@ -918,6 +885,10 @@ int ctdb_control_recv(struct ctdb_context *ctdb, } + + if (state->async.fn) { + state->async.fn(state); + } talloc_free(state); return 0; } @@ -939,8 +910,7 @@ int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid, state = ctdb_control_send(ctdb, destnode, srvid, opcode, flags, data, mem_ctx, outdata, - timeout, errormsg, - NULL, NULL); + timeout, errormsg); return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status, errormsg); } @@ -1066,8 +1036,7 @@ ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct { return ctdb_control_send(ctdb, destnode, 0, CTDB_CONTROL_GET_RECMODE, 0, tdb_null, - mem_ctx, NULL, &timeout, NULL, - NULL, NULL); + mem_ctx, NULL, &timeout, NULL); } int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode) @@ -1129,13 +1098,11 @@ int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint */ struct ctdb_client_control_state * ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, - struct timeval timeout, uint32_t destnode, - control_callback callback, void *cb_private) + struct timeval timeout, uint32_t destnode) { return ctdb_control_send(ctdb, destnode, 0, CTDB_CONTROL_GET_RECMASTER, 0, tdb_null, - mem_ctx, NULL, &timeout, NULL, - callback, cb_private); + mem_ctx, NULL, &timeout, NULL); } int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster) @@ -1160,7 +1127,7 @@ int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struc { struct ctdb_client_control_state *state; - state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode, NULL, NULL); + state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode); return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster); } diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index 17cf2c598f4..8f52aa79a0b 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -98,15 +98,24 @@ struct ctdb_call_info { enum control_state {CTDB_CONTROL_WAIT, CTDB_CONTROL_DONE, CTDB_CONTROL_ERROR, CTDB_CONTROL_TIMEOUT}; -struct ctdb_control_cb_data { - enum control_state state; - uint32_t vnn; +struct ctdb_client_control_state { + struct ctdb_context *ctdb; + uint32_t reqid; int32_t status; TDB_DATA outdata; + enum control_state state; char *errormsg; -}; + struct ctdb_req_control *c; -typedef int (*control_callback)(struct ctdb_control_cb_data *cb_data, void *cb_private); + /* if we have a callback registered for the completion (or failure) of + this control + if a callback is used, it MUST talloc_free the cb_data passed to it + */ + struct { + void (*fn)(struct ctdb_client_control_state *); + void *private; + } async; +}; struct event_context; @@ -340,7 +349,7 @@ int ctdb_ctrl_setmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint */ int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster); -struct ctdb_client_control_state *ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, control_callback callback, void *cb_private); +struct ctdb_client_control_state *ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode); int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster); diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 1c63daf469b..8a61131593d 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -861,8 +861,7 @@ ctdb_control_send(struct ctdb_context *ctdb, uint32_t opcode, uint32_t flags, TDB_DATA data, TALLOC_CTX *mem_ctx, TDB_DATA *outdata, struct timeval *timeout, - char **errormsg, - control_callback callback, void *cb_private); + char **errormsg); diff --git a/ctdb/server/ctdb_recoverd.c b/ctdb/server/ctdb_recoverd.c index 208db3963d5..f23dcea2704 100644 --- a/ctdb/server/ctdb_recoverd.c +++ b/ctdb/server/ctdb_recoverd.c @@ -1209,9 +1209,9 @@ struct verify_recmaster_data { enum monitor_result status; }; -static int verify_recmaster_callback(struct ctdb_control_cb_data *cb_data, void *cb_private) +static void verify_recmaster_callback(struct ctdb_client_control_state *state) { - struct verify_recmaster_data *rmdata = talloc_get_type(cb_private, struct verify_recmaster_data); + struct verify_recmaster_data *rmdata = talloc_get_type(state->async.private, struct verify_recmaster_data); /* one more node has responded with recmaster data*/ @@ -1220,22 +1220,22 @@ static int verify_recmaster_callback(struct ctdb_control_cb_data *cb_data, void /* if we failed to get the recmaster, then return an error and let the main loop try again. */ - if (cb_data->state != CTDB_CONTROL_DONE) { + if (state->state != CTDB_CONTROL_DONE) { if (rmdata->status == MONITOR_OK) { rmdata->status = MONITOR_FAILED; } - return 0; + return; } /* if we got a response, then the recmaster will be stored in the status field */ - if (cb_data->status != rmdata->vnn) { - DEBUG(0,("Node %d does not agree we are the recmaster. Need a new recmaster election\n",cb_data->vnn)); + if (state->status != rmdata->vnn) { + DEBUG(0,("Node %d does not agree we are the recmaster. Need a new recmaster election\n", state->c->hdr.destnode)); rmdata->status = MONITOR_ELECTION_NEEDED; } - return 0; + return; } @@ -1262,8 +1262,7 @@ static enum monitor_result verify_recmaster(struct ctdb_context *ctdb, struct ct } state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, CONTROL_TIMEOUT(), - nodemap->nodes[j].vnn, - verify_recmaster_callback, rmdata); + nodemap->nodes[j].vnn); if (state == NULL) { /* we failed to send the control, treat this as an error and try again next iteration @@ -1273,6 +1272,10 @@ static enum monitor_result verify_recmaster(struct ctdb_context *ctdb, struct ct return MONITOR_FAILED; } + /* set up the callback functions */ + state->async.fn = verify_recmaster_callback; + state->async.private = rmdata; + /* one more control to wait for to complete */ rmdata->count++; }