mirror of
https://github.com/samba-team/samba.git
synced 2025-01-10 01:18:15 +03:00
change the api for managing callbacks to controls so that isntead of
passing it as a parameter we set the callback function explicitely from the caller if the ..._send() function returned a valid state pointer. (This used to be ctdb commit aa939570662786455f63299b62c99882cff29d42)
This commit is contained in:
parent
1da9c03b1f
commit
495a6403da
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
@ -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++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user