diff --git a/ctdb/common/ctdb.c b/ctdb/common/ctdb.c index ff0829ba4dc..8a8d52f3f1f 100644 --- a/ctdb/common/ctdb.c +++ b/ctdb/common/ctdb.c @@ -274,7 +274,7 @@ static void ctdb_node_connected(struct ctdb_node *node) /* wait for all nodes to be connected */ -void ctdb_connect_wait(struct ctdb_context *ctdb) +void ctdb_daemon_connect_wait(struct ctdb_context *ctdb) { int expected = ctdb->num_nodes - 1; if (ctdb->flags & CTDB_FLAG_SELF_CONNECT) { diff --git a/ctdb/common/ctdb_client.c b/ctdb/common/ctdb_client.c index f2e551091ce..30049b76d8d 100644 --- a/ctdb/common/ctdb_client.c +++ b/ctdb/common/ctdb_client.c @@ -38,6 +38,16 @@ static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_head } +/* + handle a connect wait reply packet + */ +static void ctdb_reply_connect_wait(struct ctdb_context *ctdb, + struct ctdb_req_header *hdr) +{ + struct ctdb_reply_connect_wait *r = (struct ctdb_reply_connect_wait *)hdr; + ctdb->num_connected = r->num_connected; +} + /* this is called in the client, when data comes in from the daemon */ @@ -75,6 +85,10 @@ static void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args) case CTDB_REQ_MESSAGE: ctdb_request_message(ctdb, hdr); break; + + case CTDB_REPLY_CONNECT_WAIT: + ctdb_reply_connect_wait(ctdb, hdr); + break; } } @@ -317,6 +331,9 @@ int ctdb_set_message_handler(struct ctdb_context *ctdb, } +/* + send a message - from client context + */ int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t vnn, uint32_t srvid, TDB_DATA data) { @@ -347,3 +364,42 @@ int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t vnn, talloc_free(r); return 0; } + +/* + wait for all nodes to be connected - from client + */ +static void ctdb_client_connect_wait(struct ctdb_context *ctdb) +{ + struct ctdb_req_connect_wait r; + int res; + + ZERO_STRUCT(r); + + r.hdr.length = sizeof(r); + r.hdr.ctdb_magic = CTDB_MAGIC; + r.hdr.ctdb_version = CTDB_VERSION; + r.hdr.operation = CTDB_REQ_CONNECT_WAIT; + + res = ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)&r.hdr, r.hdr.length); + if (res != 0) { + printf("Failed to queue a connect wait request\n"); + return; + } + + /* now we can go into the normal wait routine, as the reply packet + will update the ctdb->num_connected variable */ + ctdb_daemon_connect_wait(ctdb); +} + +/* + wait for all nodes to be connected +*/ +void ctdb_connect_wait(struct ctdb_context *ctdb) +{ + if (!(ctdb->flags & CTDB_FLAG_DAEMON_MODE)) { + ctdb_daemon_connect_wait(ctdb); + return; + } + + ctdb_client_connect_wait(ctdb); +} diff --git a/ctdb/common/ctdb_daemon.c b/ctdb/common/ctdb_daemon.c index fd656cc0fb5..590397a2026 100644 --- a/ctdb/common/ctdb_daemon.c +++ b/ctdb/common/ctdb_daemon.c @@ -76,6 +76,8 @@ static void daemon_message_handler(struct ctdb_context *ctdb, uint32_t srvid, /*XXX cant use this since it returns an int CTDB_NO_MEMORY(ctdb, r);*/ talloc_set_name_const(r, "req_message packet"); + ZERO_STRUCT(*r); + r->hdr.length = len; r->hdr.ctdb_magic = CTDB_MAGIC; r->hdr.ctdb_version = CTDB_VERSION; @@ -108,6 +110,34 @@ static void daemon_request_register_message_handler(struct ctdb_client *client, } +/* + called when the daemon gets a connect wait request from a client + */ +static void daemon_request_connect_wait(struct ctdb_client *client, + struct ctdb_req_connect_wait *c) +{ + struct ctdb_reply_connect_wait r; + int res; + + /* first wait - in the daemon */ + ctdb_daemon_connect_wait(client->ctdb); + + /* now send the reply */ + ZERO_STRUCT(r); + + r.hdr.length = sizeof(r); + r.hdr.ctdb_magic = CTDB_MAGIC; + r.hdr.ctdb_version = CTDB_VERSION; + r.hdr.operation = CTDB_REPLY_CONNECT_WAIT; + r.num_connected = client->ctdb->num_connected; + + res = ctdb_queue_send(client->queue, (uint8_t *)&r.hdr, r.hdr.length); + if (res != 0) { + printf("Failed to queue a connect wait response\n"); + return; + } +} + /* destroy a ctdb_client */ @@ -236,6 +266,10 @@ static void client_incoming_packet(struct ctdb_client *client, void *data, size_ case CTDB_REQ_MESSAGE: daemon_request_message_from_client(client, (struct ctdb_req_message *)hdr); break; + + case CTDB_REQ_CONNECT_WAIT: + daemon_request_connect_wait(client, (struct ctdb_req_connect_wait *)hdr); + break; } done: diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 0f6f57e50a1..fb6a2584a96 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -199,14 +199,16 @@ struct ctdb_call_state { operation IDs */ enum ctdb_operation { - CTDB_REQ_CALL = 0, - CTDB_REPLY_CALL = 1, - CTDB_REPLY_REDIRECT = 2, - CTDB_REQ_DMASTER = 3, - CTDB_REPLY_DMASTER = 4, - CTDB_REPLY_ERROR = 5, - CTDB_REQ_REGISTER = 6, - CTDB_REQ_MESSAGE = 7 + CTDB_REQ_CALL = 0, + CTDB_REPLY_CALL = 1, + CTDB_REPLY_REDIRECT = 2, + CTDB_REQ_DMASTER = 3, + CTDB_REPLY_DMASTER = 4, + CTDB_REPLY_ERROR = 5, + CTDB_REQ_REGISTER = 6, + CTDB_REQ_MESSAGE = 7, + CTDB_REQ_CONNECT_WAIT = 8, + CTDB_REPLY_CONNECT_WAIT = 9 }; #define CTDB_MAGIC 0x43544442 /* CTDB */ @@ -281,6 +283,15 @@ struct ctdb_req_message { uint8_t data[1]; }; +struct ctdb_req_connect_wait { + struct ctdb_req_header hdr; +}; + +struct ctdb_reply_connect_wait { + struct ctdb_req_header hdr; + uint32_t num_connected; +}; + /* internal prototypes */ void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); void ctdb_fatal(struct ctdb_context *ctdb, const char *msg); @@ -382,4 +393,9 @@ int ctdb_daemon_send_message(struct ctdb_context *ctdb, uint32_t vnn, uint32_t srvid, TDB_DATA data); +/* + wait for all nodes to be connected +*/ +void ctdb_daemon_connect_wait(struct ctdb_context *ctdb); + #endif