}
-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
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;
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);
- }
- cb_data->state = state->state;
- cb_data->vnn = state->c->hdr.destnode;
+ ret = ctdb_control_recv(ctdb, state, state,
+ &state->outdata,
+ &state->status,
+ &state->errormsg);
- 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);
}
/* 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);
}
}
/* 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);
}
}
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;
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);
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;
}
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);
}
+
+ if (state->async.fn) {
+ state->async.fn(state);
+ }
talloc_free(state);
return 0;
}
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);
}
{
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)
*/
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)
{
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);
}
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;
+
+ /* 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;
};
-typedef int (*control_callback)(struct ctdb_control_cb_data *cb_data, void *cb_private);
-
struct event_context;
*/
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);
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*/
/* 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;
}
}
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
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++;
}