From 99f2177e8fbf7f288fa896a0c64bfb6ae03b9ada Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 31 Oct 2011 16:30:38 +0100 Subject: s3-ctdb: Make use of CTDB_CONTROL_CHECK_SRVIDS This should be a lot quicker than PROCESS_EXISTS followed by looking at serverid.tdb Autobuild-User: Volker Lendecke Autobuild-Date: Wed Nov 30 12:47:27 CET 2011 on sn-devel-104 --- source3/configure.in | 23 +++++ source3/include/ctdbd_conn.h | 4 + source3/lib/ctdbd_conn.c | 212 ++++++++++++++++++++++++++++++++++++++++++- source3/lib/serverid.c | 13 +++ 4 files changed, 250 insertions(+), 2 deletions(-) diff --git a/source3/configure.in b/source3/configure.in index 529b29b044..46c98aa12c 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -5547,6 +5547,29 @@ if test "x$have_cluster_support" = "xyes" ; then fi fi +if test "x$have_cluster_support" = "xyes" ; then + AC_HAVE_DECL(CTDB_CONTROL_CHECK_SRVIDS,[ + #include "confdefs.h" + #define NO_CONFIG_H + #include "replace.h" + #include "system/wait.h" + #include "system/network.h" + #include + #include + #include + #include + ]) + if test x"$ac_cv_have_CTDB_CONTROL_CHECK_SRVIDS_decl" != x"yes" + then + if test "x$enable_old_ctdb" = "xyes" ; then + AC_MSG_WARN([ignoring missing CHECK_SRVIDS (--enable-old-ctdb)]) + else + ctdb_broken="support for CHECK_SRVIDS control missing" + have_cluster_support=no + fi + fi +fi + if test "x$have_cluster_support" = "xyes" ; then # In ctdb 1.0.57, ctdb_control_tcp was temporarily renamed # to ctdb_tcp_client. diff --git a/source3/include/ctdbd_conn.h b/source3/include/ctdbd_conn.h index 1d52577fe8..9a3c27cdb9 100644 --- a/source3/include/ctdbd_conn.h +++ b/source3/include/ctdbd_conn.h @@ -46,6 +46,9 @@ bool ctdbd_process_exists(struct ctdbd_connection *conn, uint32 vnn, bool ctdb_processes_exist(struct ctdbd_connection *conn, const struct server_id *pids, int num_pids, bool *results); +bool ctdb_serverids_exist(struct ctdbd_connection *conn, + const struct server_id *pids, unsigned num_pids, + bool *results); char *ctdbd_dbpath(struct ctdbd_connection *conn, TALLOC_CTX *mem_ctx, uint32_t db_id); @@ -79,5 +82,6 @@ NTSTATUS ctdbd_control_local(struct ctdbd_connection *conn, uint32 opcode, int *cstatus); NTSTATUS ctdb_watch_us(struct ctdbd_connection *conn); NTSTATUS ctdb_unwatch(struct ctdbd_connection *conn); +NTSTATUS register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid); #endif /* _CTDBD_CONN_H */ diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index e0bdbd05a5..940d477da1 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -107,8 +107,7 @@ static void ctdb_packet_dump(struct ctdb_req_header *hdr) /* * Register a srvid with ctdbd */ -static NTSTATUS register_with_ctdbd(struct ctdbd_connection *conn, - uint64_t srvid) +NTSTATUS register_with_ctdbd(struct ctdbd_connection *conn, uint64_t srvid) { int cstatus; @@ -1032,6 +1031,215 @@ fail: return result; } +struct ctdb_vnn_list { + uint32_t vnn; + uint32_t reqid; + unsigned num_srvids; + unsigned num_filled; + uint64_t *srvids; + unsigned *pid_indexes; +}; + +/* + * Get a list of all vnns mentioned in a list of + * server_ids. vnn_indexes tells where in the vnns array we have to + * place the pids. + */ +static bool ctdb_collect_vnns(TALLOC_CTX *mem_ctx, + const struct server_id *pids, unsigned num_pids, + struct ctdb_vnn_list **pvnns, + unsigned *pnum_vnns) +{ + struct ctdb_vnn_list *vnns = NULL; + unsigned *vnn_indexes = NULL; + unsigned i, num_vnns = 0; + + vnn_indexes = talloc_array(mem_ctx, unsigned, num_pids); + if (vnn_indexes == NULL) { + goto fail; + } + + for (i=0; isrvids = talloc_array(vnns, uint64_t, vnn->num_srvids); + if (vnn->srvids == NULL) { + goto fail; + } + vnn->pid_indexes = talloc_array(vnns, unsigned, + vnn->num_srvids); + if (vnn->pid_indexes == NULL) { + goto fail; + } + } + for (i=0; isrvids[vnn->num_filled] = pids[i].unique_id; + vnn->pid_indexes[vnn->num_filled] = i; + vnn->num_filled += 1; + } + + TALLOC_FREE(vnn_indexes); + *pvnns = vnns; + *pnum_vnns = num_vnns; + return true; +fail: + TALLOC_FREE(vnns); + TALLOC_FREE(vnn_indexes); + return false; +} + +bool ctdb_serverids_exist(struct ctdbd_connection *conn, + const struct server_id *pids, unsigned num_pids, + bool *results) +{ + unsigned i, num_received; + NTSTATUS status; + struct ctdb_vnn_list *vnns = NULL; + unsigned num_vnns; + bool result = false; + + if (!ctdb_collect_vnns(talloc_tos(), pids, num_pids, + &vnns, &num_vnns)) { + goto fail; + } + + for (i=0; ireqid = ctdbd_next_reqid(conn); + + ZERO_STRUCT(req); + + DEBUG(10, ("Requesting VNN %d, reqid=%d, num_srvids=%u\n", + (int)vnn->vnn, (int)vnn->reqid, vnn->num_srvids)); + + req.hdr.length = offsetof(struct ctdb_req_control, data); + req.hdr.ctdb_magic = CTDB_MAGIC; + req.hdr.ctdb_version = CTDB_VERSION; + req.hdr.operation = CTDB_REQ_CONTROL; + req.hdr.reqid = vnn->reqid; + req.hdr.destnode = vnn->vnn; + req.opcode = CTDB_CONTROL_CHECK_SRVIDS; + req.srvid = 0; + req.datalen = sizeof(uint64_t) * vnn->num_srvids; + req.hdr.length += req.datalen; + req.flags = 0; + + DEBUG(10, ("ctdbd_control: Sending ctdb packet\n")); + ctdb_packet_dump(&req.hdr); + + status = ctdb_packet_send( + conn->pkt, 2, + data_blob_const( + &req, offsetof(struct ctdb_req_control, + data)), + data_blob_const(vnn->srvids, req.datalen)); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("ctdb_packet_send failed: %s\n", + nt_errstr(status))); + goto fail; + } + } + + status = ctdb_packet_flush(conn->pkt); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("ctdb_packet_flush failed: %s\n", + nt_errstr(status))); + goto fail; + } + + num_received = 0; + + while (num_received < num_vnns) { + struct ctdb_reply_control *reply = NULL; + struct ctdb_vnn_list *vnn; + uint32_t reqid; + + status = ctdb_read_req(conn, 0, talloc_tos(), (void *)&reply); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("ctdb_read_req failed: %s\n", + nt_errstr(status))); + goto fail; + } + + if (reply->hdr.operation != CTDB_REPLY_CONTROL) { + DEBUG(10, ("Received invalid reply\n")); + goto fail; + } + + reqid = reply->hdr.reqid; + + DEBUG(10, ("Received reqid %d\n", (int)reqid)); + + for (i=0; inum_srvids %u, datalen %u\n", + (unsigned)vnn->vnn, vnn->num_srvids, + (unsigned)reply->datalen)); + + if (reply->datalen < ((vnn->num_srvids+7)/8)) { + DEBUG(10, ("Received short reply\n")); + goto fail; + } + + for (i=0; inum_srvids; i++) { + results[vnn->pid_indexes[i]] = + ((reply->data[i/8] & (1<<(i%8))) != 0); + } + + TALLOC_FREE(reply); + num_received += 1; + } + + result = true; +fail: + TALLOC_FREE(vnns); + return result; +} + /* * Get a db path */ diff --git a/source3/lib/serverid.c b/source3/lib/serverid.c index 274b44b86f..c1b87f7929 100644 --- a/source3/lib/serverid.c +++ b/source3/lib/serverid.c @@ -25,6 +25,8 @@ #include "dbwrap/dbwrap_open.h" #include "lib/util/tdb_wrap.h" #include "lib/param/param.h" +#include "ctdbd_conn.h" +#include "messages.h" struct serverid_key { pid_t pid; @@ -122,6 +124,11 @@ bool serverid_register(const struct server_id id, uint32_t msg_flags) nt_errstr(status))); goto done; } +#ifdef HAVE_CTDB_CONTROL_CHECK_SRVIDS_DECL + if (lp_clustering()) { + register_with_ctdbd(messaging_ctdbd_connection(), id.unique_id); + } +#endif ret = true; done: TALLOC_FREE(rec); @@ -278,6 +285,12 @@ bool serverids_exist(const struct server_id *ids, int num_ids, bool *results) struct db_context *db; int i; +#ifdef HAVE_CTDB_CONTROL_CHECK_SRVIDS_DECL + if (lp_clustering()) { + return ctdb_serverids_exist(messaging_ctdbd_connection(), + ids, num_ids, results); + } +#endif if (!processes_exist(ids, num_ids, results)) { return false; } -- cgit